diff --git a/.github/workflows/test-on-push-and-pr.yml b/.github/workflows/test-on-push-and-pr.yml index 1c95bbb2..3a4b7150 100644 --- a/.github/workflows/test-on-push-and-pr.yml +++ b/.github/workflows/test-on-push-and-pr.yml @@ -15,20 +15,10 @@ jobs: node-version: [18, 20, 22] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Build and run tests for Node.js ${{ matrix.node-version }} run: | docker build -f test/unit/Dockerfile.nodejs${{ matrix.node-version }}.x -t unit/nodejs.${{ matrix.node-version }}x . docker run unit/nodejs.${{ matrix.node-version }}x - integration-test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - distro: [alpine, amazonlinux, centos, debian, ubuntu] - steps: - - uses: actions/checkout@v4 - - name: Run ${{ matrix.distro }} integration tests - run: DISTRO=${{ matrix.distro }} make test-integ diff --git a/Makefile b/Makefile index 9ff17f76..867468c1 100644 --- a/Makefile +++ b/Makefile @@ -8,15 +8,6 @@ init: test: npm run test -setup-codebuild-agent: - docker build -t codebuild-agent - < test/integration/codebuild-local/Dockerfile.agent - -test-smoke: setup-codebuild-agent - CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.1.yml alpine 3.16 18 - -test-integ: setup-codebuild-agent - CODEBUILD_IMAGE_TAG=codebuild-agent DISTRO="$(DISTRO)" test/integration/codebuild-local/test_all.sh test/integration/codebuild - copy-files: npm run copy-files @@ -30,7 +21,7 @@ format: dev: init test # Verifications to run before sending a pull request -pr: build dev test-smoke +pr: build dev clean: npm run clean @@ -42,7 +33,7 @@ build: copy-files pack: build npm pack -.PHONY: target init test setup-codebuild-agent test-smoke test-integ install format dev pr clean build pack copy-files +.PHONY: target init test install format dev pr clean build pack copy-files define HELP_MESSAGE diff --git a/README.md b/README.md index 789180cf..3c6dc8a4 100644 --- a/README.md +++ b/README.md @@ -162,8 +162,6 @@ make init build ``` Then, * to run unit tests: `make test` -* to run integration tests: `make test-integ` -* to run smoke tests: `make test-smoke` ### Raising a PR When modifying dependencies (`package.json`), make sure to: diff --git a/RELEASE.CHANGELOG.md b/RELEASE.CHANGELOG.md new file mode 100644 index 00000000..078a3cf8 --- /dev/null +++ b/RELEASE.CHANGELOG.md @@ -0,0 +1,78 @@ +### May 21, 2025 +`3.3.0` +- Add support for multi tenancy ([#128](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/128)) + +### Aug 26, 2024 +`3.2.1` +- Update test dependencies ([#115](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/115)) +- Fix autoconf build issue ([#117](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/117)) + +### Jul 03, 2024 +`3.2.0` +- Introduce advanced logging controls ([#91](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/91)) +- Bump package-lock deps ([#98](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/98)) +- Remove Node14 from integ tests matrix since it is deprecated ([#99](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/99)) +- Bump tar from 6.1.15 to 6.2.1 ([#103](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/103)) +- Handle invalid char when sending HTTP request to Runtime API ([#100](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/100)) +- Bump braces from 3.0.2 to 3.0.3 ([#109](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/109)) +- Update codebuild_build.sh script ([#110](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/110)) +- Fix centos and ubuntu integ tests ([#111](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/111)) +- Encode request id in URI path ([#113](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/113)) +- Release aws-lambda-ric 3.2.0 ([#114](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/114)) + +### Nov 09, 2023 +`3.1.0` +- tar using --no-same-owner by @JavaScriptBach ([#46](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/46)) +- Use python3.8 in al2 integ tests ([#72](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/72)) +- Create pull request template ([#73](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/73)) +- Bump deps ([#79](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/79)) +- Remove unrecognized --disable-websockets option ([#80](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/80)) +- Update Distros and integration tests ([#82](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/82)) +- Clean up images after running integ tests ([#84](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/84)) +- Add Alpine3.17,3.18 remove 3.15 for integ tests ([#85](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/85)) +- Bump @babel/traverse from 7.22.5 to 7.23.2 ([#86](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/86)) +- Add Node20 to the test matrix ([#87](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/87)) +- Release aws-lambda-ric 3.1.0 ([#88](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/88)) + +### Jun 26, 2023 +`3.0.0` +- AWS Lambda response streaming support +- ES module support +- Migrate from TypeScript to JavaScript, Include type declaration files for TypeScript support. +- Support Amazon Linux 2023 +- Update RIE to v1.12 +- Reduce image size by deleting aws-lambda-cpp and curl dependencies after building them +- aws-lambda-ric 3.0.0 release ([#70](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/70)) +- Run integration tests against every distro on PR ([#71](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/71)) + + +### May 15, 2023 +`2.1.0` +- Allow passing HandlerFunction to run function directly ([#20](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/20)) +- Update dependencies: tar and ansi-regex ([#38](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/38)) +- Bump minimist from 1.2.5 to 1.2.6 ([#48](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/48)) +- Update Curl to 7.83.0 ([#49](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/49)) +- Update Curl to 7.84.0 ([#52](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/52)) +- update aws-lambda-cpp ([#57](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/57)) +- Bump minimatch and mocha ([#58](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/58)) +- Update dependencies and distros ([#65](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/65)) +- Revert libcurl 7.84.0 update ([#66](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/66)) +- Stage aws-lambda-ric 2.1.0 release ([#67](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/67)) + +### Sep 29, 2021 +`2.0.0` +- AWS Lambda Runtime Interface Client for NodeJS with ARM64 support + +### Jun 09, 2021 +`1.1.0` +- Update Curl version to 7.77.0 ([#23](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/23)) +- Update dependencies, remove unused dependencies, add prettier plugin to eslint ([#19](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/19)) +- Fix errors issues +- Remove trailing . from sample curl command +- Add `docker login` to fix pull rate limit issue ([#2](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/2)) +- Include GitHub action on push and pr ([#1](https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/pull/1)) + +### Dec 01, 2020 +`1.0.0` +- Initial release of AWS Lambda Runtime Interface Client for NodeJS + diff --git a/deps/aws-lambda-cpp-0.2.8.tar.gz b/deps/aws-lambda-cpp-0.2.8.tar.gz index 1de32b7d..80d75c07 100644 Binary files a/deps/aws-lambda-cpp-0.2.8.tar.gz and b/deps/aws-lambda-cpp-0.2.8.tar.gz differ diff --git a/deps/patches/aws-lambda-cpp-add-tenant-id.patch b/deps/patches/aws-lambda-cpp-add-tenant-id.patch new file mode 100644 index 00000000..c4ffb243 --- /dev/null +++ b/deps/patches/aws-lambda-cpp-add-tenant-id.patch @@ -0,0 +1,40 @@ +diff --git a/include/aws/lambda-runtime/runtime.h b/include/aws/lambda-runtime/runtime.h +index f7cb8ef..833b69d 100644 +--- a/include/aws/lambda-runtime/runtime.h ++++ b/include/aws/lambda-runtime/runtime.h +@@ -56,6 +56,11 @@ struct invocation_request { + */ + std::string function_arn; + ++ /** ++ * The Tenant ID of the current invocation. ++ */ ++ std::string tenant_id; ++ + /** + * Function execution deadline counted in milliseconds since the Unix epoch. + */ +diff --git a/src/runtime.cpp b/src/runtime.cpp +index d1e655f..bcc217d 100644 +--- a/src/runtime.cpp ++++ b/src/runtime.cpp +@@ -40,6 +40,7 @@ static constexpr auto CLIENT_CONTEXT_HEADER = "lambda-runtime-client-context"; + static constexpr auto COGNITO_IDENTITY_HEADER = "lambda-runtime-cognito-identity"; + static constexpr auto DEADLINE_MS_HEADER = "lambda-runtime-deadline-ms"; + static constexpr auto FUNCTION_ARN_HEADER = "lambda-runtime-invoked-function-arn"; ++static constexpr auto TENANT_ID_HEADER = "lambda-runtime-aws-tenant-id"; + + enum Endpoints { + INIT, +@@ -296,6 +297,11 @@ runtime::next_outcome runtime::get_next() + req.function_arn = std::move(out).get_result(); + } + ++ out = resp.get_header(TENANT_ID_HEADER); ++ if (out.is_success()) { ++ req.tenant_id = std::move(out).get_result(); ++ } ++ + out = resp.get_header(DEADLINE_MS_HEADER); + if (out.is_success()) { + auto const& deadline_string = std::move(out).get_result(); diff --git a/package-lock.json b/package-lock.json index 1eb57207..e31ee745 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "aws-lambda-ric", - "version": "3.2.1", + "version": "3.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "aws-lambda-ric", - "version": "3.2.1", + "version": "3.3.0", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -1411,9 +1411,10 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1501,9 +1502,10 @@ } }, "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -3584,9 +3586,9 @@ } }, "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 83fa865e..dbf0360a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aws-lambda-ric", - "version": "3.2.1", + "version": "3.3.0", "description": "AWS Lambda Runtime Interface Client for NodeJs", "homepage": "https://github.com/aws/aws-lambda-nodejs-runtime-interface-client", "main": "dist/index.mjs", diff --git a/scripts/update_dependencies.sh b/scripts/update_dependencies.sh index 0bc6e990..4f48182d 100755 --- a/scripts/update_dependencies.sh +++ b/scripts/update_dependencies.sh @@ -29,7 +29,8 @@ wget -c https://github.com/awslabs/aws-lambda-cpp/archive/refs/tags/v$AWS_LAMBDA # Apply patches ( cd aws-lambda-cpp-$AWS_LAMBDA_CPP_RELEASE && \ - patch -p1 < ../patches/aws-lambda-cpp-add-xray-response.patch + patch -p1 < ../patches/aws-lambda-cpp-add-xray-response.patch && \ + patch -p1 < ../patches/aws-lambda-cpp-add-tenant-id.patch ) # Pack again and remove the folder diff --git a/src/Errors.js b/src/Errors.js index 6f92075c..c3028991 100644 --- a/src/Errors.js +++ b/src/Errors.js @@ -38,9 +38,9 @@ function toRapidResponse(error) { try { if (util.types.isNativeError(error) || _isError(error)) { return { - errorType: error.name?.replace(/\x7F/g, '%7F'), - errorMessage: error.message?.replace(/\x7F/g, '%7F'), - trace: error.stack.replace(/\x7F/g, '%7F').split('\n'), + errorType: error.name?.replaceAll('\x7F', '%7F'), + errorMessage: error.message?.replaceAll('\x7F', '%7F'), + trace: error.stack.replaceAll('\x7F', '%7F').split('\n'), }; } else { return { @@ -106,6 +106,13 @@ const errorClasses = [ class UserCodeSyntaxError extends Error {}, class MalformedStreamingHandler extends Error {}, class InvalidStreamingOperation extends Error {}, + class NodeJsExit extends Error { + constructor() { + super( + 'The Lambda runtime client detected an unexpected Node.js exit code. This is most commonly caused by a Promise that was never settled. For more information, see https://nodejs.org/docs/latest/api/process.html#exit-codes', + ); + } + }, class UnhandledPromiseRejection extends Error { constructor(reason, promise) { super(reason); diff --git a/src/InvokeContext.js b/src/InvokeContext.js index dab10d34..376c6359 100644 --- a/src/InvokeContext.js +++ b/src/InvokeContext.js @@ -9,7 +9,7 @@ 'use strict'; const assert = require('assert').strict; -let { setCurrentRequestId } = require('./LogPatch'); +let { setCurrentRequestId, setCurrentTenantId } = require('./LogPatch'); const INVOKE_HEADER = { ClientContext: 'lambda-runtime-client-context', @@ -18,6 +18,7 @@ const INVOKE_HEADER = { AWSRequestId: 'lambda-runtime-aws-request-id', DeadlineMs: 'lambda-runtime-deadline-ms', XRayTrace: 'lambda-runtime-trace-id', + TenantId: 'lambda-runtime-aws-tenant-id', }; module.exports = class InvokeContext { @@ -34,11 +35,19 @@ module.exports = class InvokeContext { return id; } + /** + * The tenantId for this request. + */ + get tenantId() { + return this.headers[INVOKE_HEADER.TenantId]; + } + /** * Push relevant invoke data into the logging context. */ updateLoggingContext() { setCurrentRequestId(this.invokeId); + setCurrentTenantId(this.tenantId); } /** @@ -91,6 +100,7 @@ module.exports = class InvokeContext { ), invokedFunctionArn: this.headers[INVOKE_HEADER.ARN], awsRequestId: this.headers[INVOKE_HEADER.AWSRequestId], + tenantId: this.headers[INVOKE_HEADER.TenantId], getRemainingTimeInMillis: function () { return deadline - Date.now(); }, diff --git a/src/LogPatch.js b/src/LogPatch.js index 071de9d4..50757ab4 100644 --- a/src/LogPatch.js +++ b/src/LogPatch.js @@ -28,13 +28,23 @@ const jsonErrorReplacer = (_, value) => { return value; }; -function formatJsonMessage(requestId, timestamp, level, ...messageParams) { +function formatJsonMessage( + requestId, + timestamp, + level, + tenantId, + ...messageParams +) { let result = { timestamp: timestamp, level: level.name, requestId: requestId, }; + if (tenantId != undefined && tenantId != null) { + result.tenantId = tenantId; + } + if (messageParams.length === 1) { result.message = messageParams[0]; try { @@ -65,6 +75,13 @@ let _currentRequestId = { set: (id) => (global[REQUEST_ID_SYMBOL] = id), }; +/* Use a unique symbol to provide global access without risk of name clashes. */ +const TENANT_ID_SYMBOL = Symbol.for('aws.lambda.runtime.tenantId'); +let _currentTenantId = { + get: () => global[TENANT_ID_SYMBOL], + set: (id) => (global[TENANT_ID_SYMBOL] = id), +}; + /** * Write logs to stdout. */ @@ -82,7 +99,15 @@ let logTextToStdout = (level, message, ...params) => { let logJsonToStdout = (level, message, ...params) => { let time = new Date().toISOString(); let requestId = _currentRequestId.get(); - let line = formatJsonMessage(requestId, time, level, message, ...params); + let tenantId = _currentTenantId.get(); + let line = formatJsonMessage( + requestId, + time, + level, + tenantId, + message, + ...params, + ); line = line.replace(/\n/g, '\r'); process.stdout.write(line + '\n'); }; @@ -125,10 +150,12 @@ let logJsonToFd = function (logTarget) { let date = new Date(); let time = date.toISOString(); let requestId = _currentRequestId.get(); + let tenantId = _currentTenantId.get(); let enrichedMessage = formatJsonMessage( requestId, time, level, + tenantId, message, ...params, ); @@ -239,6 +266,7 @@ let _patchConsole = () => { module.exports = { setCurrentRequestId: _currentRequestId.set, + setCurrentTenantId: _currentTenantId.set, patchConsole: _patchConsole, structuredConsole: structuredConsole, }; diff --git a/src/Runtime.js b/src/Runtime.js index 8ec0baa2..77d6eaac 100644 --- a/src/Runtime.js +++ b/src/Runtime.js @@ -12,7 +12,9 @@ const CallbackContext = require('./CallbackContext.js'); const StreamingContext = require('./StreamingContext.js'); const BeforeExitListener = require('./BeforeExitListener.js'); const { STREAM_RESPONSE } = require('./UserFunction.js'); +const { NodeJsExit } = require('./Errors.js'); const { verbose, vverbose } = require('./VerboseLog.js').logger('RAPID'); +const { structuredConsole } = require('./LogPatch'); module.exports = class Runtime { constructor(client, handler, handlerMetadata, errorCallbacks) { @@ -69,7 +71,7 @@ module.exports = class Runtime { try { this._setErrorCallbacks(invokeContext.invokeId); - this._setDefaultExitListener(invokeContext.invokeId, markCompleted); + this._setDefaultExitListener(invokeContext.invokeId, markCompleted, this.handlerMetadata.isAsync); let result = this.handler( JSON.parse(bodyJson), @@ -178,12 +180,22 @@ module.exports = class Runtime { * called and the handler is not async. * CallbackContext replaces the listener if a callback is invoked. */ - _setDefaultExitListener(invokeId, markCompleted) { + _setDefaultExitListener(invokeId, markCompleted, isAsync) { BeforeExitListener.set(() => { markCompleted(); - this.client.postInvocationResponse(null, invokeId, () => - this.scheduleIteration(), - ); + // if the handle signature is async, we do want to fail the invocation + if (isAsync) { + const nodeJsExitError = new NodeJsExit(); + structuredConsole.logError('Invoke Error', nodeJsExitError); + this.client.postInvocationError(nodeJsExitError, invokeId, () => + this.scheduleIteration(), + ); + // if the handler signature is sync, or use callback, we do want to send a successful invocation with a null payload if the customer forgot to call the callback + } else { + this.client.postInvocationResponse(null, invokeId, () => + this.scheduleIteration(), + ); + } }); } diff --git a/src/UserFunction.js b/src/UserFunction.js index 1114fb40..a6e16313 100644 --- a/src/UserFunction.js +++ b/src/UserFunction.js @@ -311,10 +311,25 @@ module.exports.isHandlerFunction = function (value) { return typeof value === 'function'; }; +function _isAsync(handler) { + try { + return ( + handler && + typeof handler === 'function' && + handler.constructor && + handler.constructor.name === 'AsyncFunction' + ); + } catch (error) { + return false; + } +} + module.exports.getHandlerMetadata = function (handlerFunc) { return { streaming: _isHandlerStreaming(handlerFunc), highWaterMark: _highWaterMark(handlerFunc), + isAsync: _isAsync(handlerFunc), + argsNum: handlerFunc.length, }; }; diff --git a/src/WarningForCallbackHandlers.js b/src/WarningForCallbackHandlers.js new file mode 100644 index 00000000..7c41cf6e --- /dev/null +++ b/src/WarningForCallbackHandlers.js @@ -0,0 +1,24 @@ +/* +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +const shouldWarnOnCallbackFunctionUse = (metadata) => { + return ( + process.env.AWS_LAMBDA_NODEJS_DISABLE_CALLBACK_WARNING === undefined && + metadata !== undefined && + metadata.argsNum == 3 && + metadata.isAsync == false && + metadata.streaming == false + ); +}; + +module.exports.checkForDeprecatedCallback = function (metadata) { + if (shouldWarnOnCallbackFunctionUse(metadata)) { + console.warn( + `AWS Lambda plans to remove support for callback-based function handlers starting with Node.js 24. You will need to update this function to use an async handler to use Node.js 24 or later. For more information and to provide feedback on this change, see https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/issues/137. To disable this warning, set the AWS_LAMBDA_NODEJS_DISABLE_CALLBACK_WARNING environment variable.`, + ); + } +}; \ No newline at end of file diff --git a/src/index.mjs b/src/index.mjs index 9267866a..dd1d193e 100755 --- a/src/index.mjs +++ b/src/index.mjs @@ -11,6 +11,7 @@ const UserFunction = require('./UserFunction.js'); const Errors = require('./Errors.js'); const BeforeExitListener = require('./BeforeExitListener.js'); const LogPatch = require('./LogPatch'); +const { checkForDeprecatedCallback } = require('./WarningForCallbackHandlers'); export async function run(appRootOrHandler, handler = '') { LogPatch.patchConsole(); @@ -44,6 +45,7 @@ export async function run(appRootOrHandler, handler = '') { : await UserFunction.load(appRootOrHandler, handler); const metadata = UserFunction.getHandlerMetadata(handlerFunc); + checkForDeprecatedCallback(metadata); new Runtime( client, handlerFunc, diff --git a/src/rapid-client.cc b/src/rapid-client.cc index d02f55e1..aea0b1d7 100644 --- a/src/rapid-client.cc +++ b/src/rapid-client.cc @@ -82,6 +82,11 @@ class RuntimeApiNextPromiseWorker : public Napi::AsyncWorker { Napi::String::New(env, "lambda-runtime-cognito-identity"), Napi::String::New(env, response.cognito_identity.c_str())); } + if (response.tenant_id != "") { + headers.Set( + Napi::String::New(env, "lambda-runtime-aws-tenant-id"), + Napi::String::New(env, response.tenant_id.c_str())); + } auto ret = Napi::Object::New(env); ret.Set(Napi::String::New(env, "bodyJson"), response_data); diff --git a/test/handlers/isAsync.mjs b/test/handlers/isAsync.mjs new file mode 100644 index 00000000..03383932 --- /dev/null +++ b/test/handlers/isAsync.mjs @@ -0,0 +1,20 @@ +/* +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +export const handlerAsync = async () => { + const response = { + statusCode: 200, + body: JSON.stringify('Hello from Lambda!'), + }; + return response; +}; + +export const handlerNotAsync = () => { + const response = { + statusCode: 200, + body: JSON.stringify('Hello from Lambda!'), + }; + return response; +}; diff --git a/test/handlers/isAsyncCallback.js b/test/handlers/isAsyncCallback.js new file mode 100644 index 00000000..2c4f99c6 --- /dev/null +++ b/test/handlers/isAsyncCallback.js @@ -0,0 +1,12 @@ +/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ + +'use strict'; + +exports.handler = (_event, _context, callback) => { + callback(null, { + statusCode: 200, + body: JSON.stringify({ + message: 'hello world', + }), + }); +}; \ No newline at end of file diff --git a/test/integration/codebuild-local/Dockerfile.agent b/test/integration/codebuild-local/Dockerfile.agent deleted file mode 100644 index e9a9ffe5..00000000 --- a/test/integration/codebuild-local/Dockerfile.agent +++ /dev/null @@ -1,5 +0,0 @@ -FROM amazonlinux:2 - -RUN amazon-linux-extras enable docker && \ - yum clean metadata && \ - yum install -y docker tar diff --git a/test/integration/codebuild-local/codebuild_build.sh b/test/integration/codebuild-local/codebuild_build.sh deleted file mode 100755 index a858d940..00000000 --- a/test/integration/codebuild-local/codebuild_build.sh +++ /dev/null @@ -1,206 +0,0 @@ -#!/bin/bash -# This file is copied from https://github.com/aws/aws-codebuild-docker-images/blob/f0912e4b16e427da35351fc102f0f56f4ceb938a/local_builds/codebuild_build.sh - -function allOSRealPath() { - if isOSWindows - then - path="" - case $1 in - .* ) path="$PWD/${1#./}" ;; - /* ) path="$1" ;; - * ) path="/$1" ;; - esac - - echo "/$path" | sed -e 's/\\/\//g' -e 's/://' -e 's/./\U&/3' - else - case $1 in - /* ) echo "$1"; exit;; - * ) echo "$PWD/${1#./}"; exit;; - esac - fi -} - -function isOSWindows() { - if [ $OSTYPE == "msys" ] - then - return 0 - else - return 1 - fi -} - -function usage { - echo "usage: codebuild_build.sh [-i image_name] [-a artifact_output_directory] [options]" - echo "Required:" - echo " -i Used to specify the customer build container image." - echo " -a Used to specify an artifact output directory." - echo "Options:" - echo " -l IMAGE Used to override the default local agent image." - echo " -r Used to specify a report output directory." - echo " -s Used to specify source information. Defaults to the current working directory for primary source." - echo " * First (-s) is for primary source" - echo " * Use additional (-s) in : format for secondary source" - echo " * For sourceIdentifier, use a value that is fewer than 128 characters and contains only alphanumeric characters and underscores" - echo " -c Use the AWS configuration and credentials from your local host. This includes ~/.aws and any AWS_* environment variables." - echo " -p Used to specify the AWS CLI Profile." - echo " -b FILE Used to specify a buildspec override file. Defaults to buildspec.yml in the source directory." - echo " -m Used to mount the source directory to the customer build container directly." - echo " -d Used to run the build container in docker privileged mode." - echo " -e FILE Used to specify a file containing environment variables." - echo " (-e) File format expectations:" - echo " * Each line is in VAR=VAL format" - echo " * Lines beginning with # are processed as comments and ignored" - echo " * Blank lines are ignored" - echo " * File can be of type .env or .txt" - echo " * There is no special handling of quotation marks, meaning they will be part of the VAL" - exit 1 -} - -image_flag=false -artifact_flag=false -awsconfig_flag=false -mount_src_dir_flag=false -docker_privileged_mode_flag=false - -while getopts "cmdi:a:r:s:b:e:l:p:h" opt; do - case $opt in - i ) image_flag=true; image_name=$OPTARG;; - a ) artifact_flag=true; artifact_dir=$OPTARG;; - r ) report_dir=$OPTARG;; - b ) buildspec=$OPTARG;; - c ) awsconfig_flag=true;; - m ) mount_src_dir_flag=true;; - d ) docker_privileged_mode_flag=true;; - s ) source_dirs+=("$OPTARG");; - e ) environment_variable_file=$OPTARG;; - l ) local_agent_image=$OPTARG;; - p ) aws_profile=$OPTARG;; - h ) usage; exit;; - \? ) echo "Unknown option: -$OPTARG" >&2; exit 1;; - : ) echo "Missing option argument for -$OPTARG" >&2; exit 1;; - * ) echo "Invalid option: -$OPTARG" >&2; exit 1;; - esac -done - -if ! $image_flag -then - echo "The image name flag (-i) must be included for a build to run" >&2 -fi - -if ! $artifact_flag -then - echo "The artifact directory (-a) must be included for a build to run" >&2 -fi - -if ! $image_flag || ! $artifact_flag -then - exit 1 -fi - -docker_command="docker run " -if isOSWindows -then - docker_command+="-v //var/run/docker.sock:/var/run/docker.sock -e " -else - docker_command+="-v /var/run/docker.sock:/var/run/docker.sock -e " -fi - -docker_command+="\"IMAGE_NAME=$image_name\" -e \ - \"ARTIFACTS=$(allOSRealPath "$artifact_dir")\"" - -if [ -n "$report_dir" ] -then - docker_command+=" -e \"REPORTS=$(allOSRealPath "$report_dir")\"" -fi - -if [ -z "$source_dirs" ] -then - docker_command+=" -e \"SOURCE=$(allOSRealPath "$PWD")\"" -else - for index in "${!source_dirs[@]}"; do - if [ $index -eq 0 ] - then - docker_command+=" -e \"SOURCE=$(allOSRealPath "${source_dirs[$index]}")\"" - else - identifier=${source_dirs[$index]%%:*} - src_dir=$(allOSRealPath "${source_dirs[$index]#*:}") - - docker_command+=" -e \"SECONDARY_SOURCE_$index=$identifier:$src_dir\"" - fi - done -fi - -if [ -n "$buildspec" ] -then - docker_command+=" -e \"BUILDSPEC=$(allOSRealPath "$buildspec")\"" -fi - -if [ -n "$environment_variable_file" ] -then - environment_variable_file_path=$(allOSRealPath "$environment_variable_file") - environment_variable_file_dir=$(dirname "$environment_variable_file_path") - environment_variable_file_basename=$(basename "$environment_variable_file") - docker_command+=" -v \"$environment_variable_file_dir:/LocalBuild/envFile/\" -e \"ENV_VAR_FILE=$environment_variable_file_basename\"" -fi - -if [ -n "$local_agent_image" ] -then - docker_command+=" -e \"LOCAL_AGENT_IMAGE_NAME=$local_agent_image\"" -fi - -if $awsconfig_flag -then - if [ -d "$HOME/.aws" ] - then - configuration_file_path=$(allOSRealPath "$HOME/.aws") - docker_command+=" -e \"AWS_CONFIGURATION=$configuration_file_path\"" - else - docker_command+=" -e \"AWS_CONFIGURATION=NONE\"" - fi - - if [ -n "$aws_profile" ] - then - docker_command+=" -e \"AWS_PROFILE=$aws_profile\"" - fi - - docker_command+="$(env | grep ^AWS_ | while read -r line; do echo " -e \"$line\""; done )" -fi - -if $mount_src_dir_flag -then - docker_command+=" -e \"MOUNT_SOURCE_DIRECTORY=TRUE\"" -fi - -if $docker_privileged_mode_flag -then - docker_command+=" -e \"DOCKER_PRIVILEGED_MODE=TRUE\"" -fi - -if isOSWindows -then - docker_command+=" -e \"INITIATOR=$USERNAME\"" -else - docker_command+=" -e \"INITIATOR=$USER\"" -fi - -if [ -n "$local_agent_image" ] -then - docker_command+=" $local_agent_image" -else - docker_command+=" public.ecr.aws/codebuild/local-builds:latest" -fi - -# Note we do not expose the AWS_SECRET_ACCESS_KEY or the AWS_SESSION_TOKEN -exposed_command=$docker_command -secure_variables=( "AWS_SECRET_ACCESS_KEY=" "AWS_SESSION_TOKEN=") -for variable in "${secure_variables[@]}" -do - exposed_command="$(echo $exposed_command | sed "s/\($variable\)[^ ]*/\1********\"/")" -done - -echo "Build Command:" -echo "" -echo $exposed_command -echo "" - -eval $docker_command diff --git a/test/integration/codebuild-local/test_all.sh b/test/integration/codebuild-local/test_all.sh deleted file mode 100755 index a911db53..00000000 --- a/test/integration/codebuild-local/test_all.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set -euo pipefail - -CODEBUILD_IMAGE_TAG="${CODEBUILD_IMAGE_TAG:-al2/x86_64/standard/3.0}" -DISTRO="${DISTRO:=""}" -DRYRUN="${DRYRUN-0}" - -function usage { - echo "usage: test_all.sh buildspec_yml_dir" - echo "Runs all buildspec build-matrix combinations via test_one.sh." - echo "Required:" - echo " buildspec_yml_dir Used to specify the CodeBuild buildspec template file." -} - -do_one_yaml() { - local -r YML="$1" - - OS_DISTRIBUTION=$(grep -oE 'OS_DISTRIBUTION:\s*(\S+)' "$YML" | cut -d' ' -f2) - DISTRO_VERSIONS=$(sed '1,/DISTRO_VERSION/d;/RUNTIME_VERSION/,$d' "$YML" | tr -d '\-" ') - RUNTIME_VERSIONS=$(sed '1,/RUNTIME_VERSION/d;/phases/,$d' "$YML" | sed '/#.*$/d' | tr -d '\-" ') - - for DISTRO_VERSION in $DISTRO_VERSIONS ; do - for RUNTIME_VERSION in $RUNTIME_VERSIONS ; do - if (( DRYRUN == 1 )) ; then - echo DRYRUN test_one_combination "$YML" "$OS_DISTRIBUTION" "$DISTRO_VERSION" "$RUNTIME_VERSION" - else - test_one_combination "$YML" "$OS_DISTRIBUTION" "$DISTRO_VERSION" "$RUNTIME_VERSION" - fi - done - done -} - -test_one_combination() { - local -r YML="$1" - local -r OS_DISTRIBUTION="$2" - local -r DISTRO_VERSION="$3" - local -r RUNTIME_VERSION="$4" - - echo Testing: - echo " BUILDSPEC" "$YML" - echo " with" "$OS_DISTRIBUTION"-"$DISTRO_VERSION" "$RUNTIME_VERSION" - - "$(dirname "$0")"/test_one.sh "$YML" "$OS_DISTRIBUTION" "$DISTRO_VERSION" "$RUNTIME_VERSION" \ - > >(sed "s/^/$OS_DISTRIBUTION$DISTRO_VERSION-$RUNTIME_VERSION: /") 2> >(sed "s/^/$OS_DISTRIBUTION-$DISTRO_VERSION:$RUNTIME_VERSION: /" >&2) -} - -main() { - if (( $# != 1 && $# != 2)); then - >&2 echo "Invalid number of parameters." - usage - exit 1 - fi - - BUILDSPEC_YML_DIR="$1" - HAS_YML=0 - for f in "$BUILDSPEC_YML_DIR"/*"$DISTRO"*.yml ; do - [ -f "$f" ] || continue; - do_one_yaml "$f" - HAS_YML=1 - done - - if (( HAS_YML == 0 )); then - >&2 echo At least one buildspec is required. - exit 2 - fi -} - -main "$@" diff --git a/test/integration/codebuild-local/test_one.sh b/test/integration/codebuild-local/test_one.sh deleted file mode 100755 index 22c2f90c..00000000 --- a/test/integration/codebuild-local/test_one.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set -euo pipefail - -CODEBUILD_IMAGE_TAG="${CODEBUILD_IMAGE_TAG:-al2/x86_64/standard/3.0}" - -function usage { - >&2 echo "usage: test_one.sh buildspec_yml os_distribution distro_version runtime_version [env]" - >&2 echo "Runs one buildspec version combination from a build-matrix buildspec." - >&2 echo "Required:" - >&2 echo " buildspec_yml Used to specify the CodeBuild buildspec template file." - >&2 echo " os_distribution Used to specify the OS distribution to build." - >&2 echo " distro_version Used to specify the distro version of ." - >&2 echo " runtime_version Used to specify the runtime version to test on the selected ." - >&2 echo "Optional:" - >&2 echo " env Additional environment variables file." -} - -main() { - if (( $# != 3 && $# != 4)); then - >&2 echo "Invalid number of parameters." - usage - exit 1 - fi - - BUILDSPEC_YML="$1" - OS_DISTRIBUTION="$2" - DISTRO_VERSION="$3" - RUNTIME_VERSION="$4" - EXTRA_ENV="${5-}" - - CODEBUILD_TEMP_DIR=$(mktemp -d codebuild."$OS_DISTRIBUTION"-"$DISTRO_VERSION"-"$RUNTIME_VERSION".XXXXXXXXXX) - trap 'rm -rf $CODEBUILD_TEMP_DIR' EXIT - - # Create an env file for codebuild_build. - ENVFILE="$CODEBUILD_TEMP_DIR/.env" - if [ -f "$EXTRA_ENV" ]; then - cat "$EXTRA_ENV" > "$ENVFILE" - fi - { - echo "" - echo "OS_DISTRIBUTION=$OS_DISTRIBUTION" - echo "DISTRO_VERSION=$DISTRO_VERSION" - echo "RUNTIME_VERSION=$RUNTIME_VERSION" - } >> "$ENVFILE" - - ARTIFACTS_DIR="$CODEBUILD_TEMP_DIR/artifacts" - mkdir -p "$ARTIFACTS_DIR" - - # Run CodeBuild local agent. - "$(dirname "$0")"/codebuild_build.sh \ - -i "$CODEBUILD_IMAGE_TAG" \ - -a "$ARTIFACTS_DIR" \ - -e "$ENVFILE" \ - -b "$BUILDSPEC_YML" -} - -main "$@" diff --git a/test/integration/codebuild/buildspec.os.alpine.1.yml b/test/integration/codebuild/buildspec.os.alpine.1.yml deleted file mode 100644 index e4c14cd8..00000000 --- a/test/integration/codebuild/buildspec.os.alpine.1.yml +++ /dev/null @@ -1,111 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: alpine - NPX_BINARY_LOCATION: "/usr/local/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "3.16" - RUNTIME_VERSION: - - "16" - - "18" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "RUN apk add curl" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} ${NPX_BINARY_LOCATION} aws-lambda-ric index.handler" - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/codebuild/buildspec.os.alpine.2.yml b/test/integration/codebuild/buildspec.os.alpine.2.yml deleted file mode 100644 index a4528465..00000000 --- a/test/integration/codebuild/buildspec.os.alpine.2.yml +++ /dev/null @@ -1,102 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: alpine - NODE_BINARY_LOCATION: "/usr/local/bin/node" - NPX_BINARY_LOCATION: "/usr/local/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - type: LINUX_CONTAINER - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "3.18" - RUNTIME_VERSION: - - "20" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - tar -xvf test/integration/resources/aws-lambda-rie.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.programmatic.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.programmatic.${OS_DISTRIBUTION}.tmp" - - > - echo "RUN apk add curl" >> \ - "${SCRATCH_DIR}/Dockerfile.programmatic.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/aws-lambda-rie /usr/bin/aws-lambda-rie" >> \ - "${SCRATCH_DIR}/Dockerfile.programmatic.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.programmatic.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - -e "NODE_BINARY_LOCATION=${NODE_BINARY_LOCATION}" \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c '/usr/bin/aws-lambda-rie ${NODE_BINARY_LOCATION} index.mjs' - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" - echo - echo "---------------------------------------------------" - exit -1 - fi - finally: - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/codebuild/buildspec.os.alpine.3.yml b/test/integration/codebuild/buildspec.os.alpine.3.yml deleted file mode 100644 index 3f567878..00000000 --- a/test/integration/codebuild/buildspec.os.alpine.3.yml +++ /dev/null @@ -1,113 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: alpine - NPX_BINARY_LOCATION: "/usr/local/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "3.17" - - "3.18" - RUNTIME_VERSION: - - "16" - - "18" - - "20" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "RUN apk add curl" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} ${NPX_BINARY_LOCATION} aws-lambda-ric index.handler" - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/codebuild/buildspec.os.amazonlinux.2.yml b/test/integration/codebuild/buildspec.os.amazonlinux.2.yml deleted file mode 100644 index 9426db59..00000000 --- a/test/integration/codebuild/buildspec.os.amazonlinux.2.yml +++ /dev/null @@ -1,109 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: amazonlinux - NPX_BINARY_LOCATION: "/usr/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "2" - RUNTIME_VERSION: - - "14" - - "16" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" \ - --build-arg ARCHITECTURE="${ARCHITECTURE}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} ${NPX_BINARY_LOCATION} aws-lambda-ric index.handler" - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/codebuild/buildspec.os.amazonlinux.2023.yml b/test/integration/codebuild/buildspec.os.amazonlinux.2023.yml deleted file mode 100644 index bdda5692..00000000 --- a/test/integration/codebuild/buildspec.os.amazonlinux.2023.yml +++ /dev/null @@ -1,109 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: amazonlinux - NPX_BINARY_LOCATION: "/usr/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "2023" - RUNTIME_VERSION: - - "18" - - "20" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" \ - --build-arg ARCHITECTURE="${ARCHITECTURE}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} ${NPX_BINARY_LOCATION} aws-lambda-ric index.handler" - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/codebuild/buildspec.os.centos.yml b/test/integration/codebuild/buildspec.os.centos.yml deleted file mode 100644 index f3be37e2..00000000 --- a/test/integration/codebuild/buildspec.os.centos.yml +++ /dev/null @@ -1,109 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: centos - NPX_BINARY_LOCATION: "/usr/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "stream9" - RUNTIME_VERSION: - - "18" - - "20" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" \ - --build-arg ARCHITECTURE="${ARCHITECTURE}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} ${NPX_BINARY_LOCATION} aws-lambda-ric index.handler" - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/codebuild/buildspec.os.debian.1.yml b/test/integration/codebuild/buildspec.os.debian.1.yml deleted file mode 100644 index 82ea6bda..00000000 --- a/test/integration/codebuild/buildspec.os.debian.1.yml +++ /dev/null @@ -1,112 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: debian - NPX_BINARY_LOCATION: "/usr/local/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "buster" - - "bullseye" - RUNTIME_VERSION: - - "18" - - "20" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - > - echo "RUN apt-get update && apt-get install -y curl" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} ${NPX_BINARY_LOCATION} aws-lambda-ric index.handler" - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/codebuild/buildspec.os.debian.2.yml b/test/integration/codebuild/buildspec.os.debian.2.yml deleted file mode 100644 index 0f2c0c39..00000000 --- a/test/integration/codebuild/buildspec.os.debian.2.yml +++ /dev/null @@ -1,111 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: debian - NPX_BINARY_LOCATION: "/usr/local/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "bookworm" - RUNTIME_VERSION: - - "18" - - "20" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - > - echo "RUN apt-get update && apt-get install -y curl" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} ${NPX_BINARY_LOCATION} aws-lambda-ric index.handler" - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/codebuild/buildspec.os.ubuntu.1.yml b/test/integration/codebuild/buildspec.os.ubuntu.1.yml deleted file mode 100644 index 3875078a..00000000 --- a/test/integration/codebuild/buildspec.os.ubuntu.1.yml +++ /dev/null @@ -1,109 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: ubuntu - NPX_BINARY_LOCATION: "/usr/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "20.04" - - "22.04" - RUNTIME_VERSION: - - "18" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" \ - --build-arg ARCHITECTURE="${ARCHITECTURE}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} ${NPX_BINARY_LOCATION} aws-lambda-ric index.handler" - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/codebuild/buildspec.os.ubuntu.2.yml b/test/integration/codebuild/buildspec.os.ubuntu.2.yml deleted file mode 100644 index 95f6b226..00000000 --- a/test/integration/codebuild/buildspec.os.ubuntu.2.yml +++ /dev/null @@ -1,110 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: ubuntu - NPX_BINARY_LOCATION: "/usr/bin/npx" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "20.04" - - "22.04" - RUNTIME_VERSION: - - "18" - - "20" -phases: - pre_build: - commands: - - export IMAGE_TAG="nodejs-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" \ - --build-arg ARCHITECTURE="${ARCHITECTURE}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${OS_DISTRIBUTION}-network" - - > - docker run \ - --detach \ - --name "${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} ${NPX_BINARY_LOCATION} aws-lambda-ric index.handler" - - sleep 2 - - > - docker run \ - --name "${OS_DISTRIBUTION}-tester" \ - --env "TARGET=${OS_DISTRIBUTION}-app" \ - --network "${OS_DISTRIBUTION}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${OS_DISTRIBUTION}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${OS_DISTRIBUTION}-app----------" - echo - docker logs "${OS_DISTRIBUTION}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${OS_DISTRIBUTION}-tester--------" - echo - docker logs "${OS_DISTRIBUTION}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${OS_DISTRIBUTION}-app" || true - - docker rm --force "${OS_DISTRIBUTION}-app" || true - - docker stop "${OS_DISTRIBUTION}-tester" || true - - docker rm --force "${OS_DISTRIBUTION}-tester" || true - - docker network rm "${OS_DISTRIBUTION}-network" || true - - docker rmi "${IMAGE_TAG}" || true diff --git a/test/integration/docker/Dockerfile.echo.alpine b/test/integration/docker/Dockerfile.echo.alpine deleted file mode 100644 index 10f1aab4..00000000 --- a/test/integration/docker/Dockerfile.echo.alpine +++ /dev/null @@ -1,68 +0,0 @@ -# Define global args -ARG FUNCTION_DIR="/home/app/" -ARG RUNTIME_VERSION -ARG DISTRO_VERSION - -# Stage 1 - build function and dependencies -FROM node:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} AS build-image -# Include global arg in this stage of the build -ARG DISTRO_VERSION -# Install aws-lambda-cpp build dependencies -RUN apk add --update-cache \ - build-base \ - libtool \ - musl-dev \ - libressl-dev \ - libffi-dev \ - autoconf \ - automake \ - make \ - cmake \ - python3 \ - libcurl - -# AWS Lambda CPP and libcurl rely on backtrace which requires libexecinfo from Alpine. -# Since starting from Alpine3.17 libexecinfo is no longer available, temporarily source it from Alpine3.16 -# while awaiting an upstream resolution in AWS Lambda CPP. -RUN if [[ "${DISTRO_VERSION}" == "3.17" ]] || [[ "${DISTRO_VERSION}" == "3.18" ]] ; \ -then \ - apk add --update-cache --repository=https://dl-cdn.alpinelinux.org/alpine/v3.16/main/ libexecinfo-dev ; \ -else \ - apk add --update-cache libexecinfo-dev ; \ -fi - -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Create function directory -RUN mkdir -p ${FUNCTION_DIR} - -# Copy & build Runtime Interface Client package (as we're installing it from a local filesystem source) -WORKDIR ${FUNCTION_DIR}/deps/aws-lambda-ric -COPY . . - -RUN make build && \ - npm run test:unit - -# Copy function code -COPY test/integration/test-handlers/echo/* ${FUNCTION_DIR} -# Install the function's dependencies -WORKDIR ${FUNCTION_DIR} -RUN npm install - - -# Stage 2 - final runtime image -# Grab a fresh copy of the Node image -FROM node:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} - -# Required for Node runtimes which use npm@8.6.0+ because -# by default npm writes logs under /home/.npm and Lambda fs is read-only -ENV NPM_CONFIG_CACHE=/tmp/.npm -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Set working directory to function root directory -WORKDIR ${FUNCTION_DIR} -# Copy in the built dependencies -COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} - -ENTRYPOINT [ "/usr/local/bin/npx", "aws-lambda-ric" ] -CMD [ "index.handler" ] diff --git a/test/integration/docker/Dockerfile.echo.amazonlinux b/test/integration/docker/Dockerfile.echo.amazonlinux deleted file mode 100644 index b54956df..00000000 --- a/test/integration/docker/Dockerfile.echo.amazonlinux +++ /dev/null @@ -1,83 +0,0 @@ -# Define global args -ARG FUNCTION_DIR="/home/app/" -ARG RUNTIME_VERSION -ARG DISTRO_VERSION - -# Stage 1 - bundle base image + runtime -# Grab a fresh copy of the image and install Node -FROM amazonlinux:${DISTRO_VERSION} AS node-amazonlinux -# Include global arg in this stage of the build -ARG RUNTIME_VERSION -ARG DISTRO_VERSION -# Install Py3 required to build Node16+ -RUN if [[ "${DISTRO_VERSION}" == "2" ]] ; then amazon-linux-extras install python3.8 && update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 ; fi -# Install NodeJS -RUN if [[ "${RUNTIME_VERSION}" == "14" ]]; then \ - yum install -y tar gzip xz && \ - AARCH="$([[ "$(arch)" == "x86_64" ]] && echo "x64" || echo "arm64")" && \ - NODE_URL="https://nodejs.org/download/release/v14.21.3/node-v14.21.3-linux-$AARCH.tar.xz" && \ - curl -fL "$NODE_URL" | tar -C /usr --strip-components 1 -xJf - && \ - yum clean all -q && rm -rf /var/cache/yum ; \ -else \ - yum install https://rpm.nodesource.com/pub_${RUNTIME_VERSION}.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm -y && \ - yum install nodejs -y --setopt=nodesource-nodejs.module_hotfixes=1s ; \ -fi - -# Stage 2 - build function and dependencies -FROM node-amazonlinux AS build-image -ARG ARCHITECTURE -# Install aws-lambda-cpp build dependencies -RUN yum install -y \ - tar \ - gzip \ - make \ - wget \ - autoconf \ - automake \ - libtool \ - libcurl-devel \ - gcc-c++ -# Install a modern CMake -RUN wget --quiet -O cmake-install https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0-linux-${ARCHITECTURE}.sh && \ - sh cmake-install --skip-license --prefix=/usr --exclude-subdirectory; - -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Create function directory -RUN mkdir -p ${FUNCTION_DIR} - -# Copy & build Runtime Interface Client package (as we're installing it from a local filesystem source) -WORKDIR ${FUNCTION_DIR}/deps/aws-lambda-ric -COPY . . - -# Node14 uses npm@6.14.18 by default which will downgrade permissions, if it's root, -# before running any build scripts: https://github.com/npm/npm/issues/3497 -# Starting from npm@7.0.0, when npm is run as root, -# scripts are always run with the effective uid and gid of the working directory owner. -RUN if [[ $(node -v | cut -c 1-3) == "v14" ]] ; then npm install -g npm@7 ; fi -RUN make build && \ - npm run test:unit - -# Copy function code -COPY test/integration/test-handlers/echo/* ${FUNCTION_DIR} -# Install the function's dependencies -WORKDIR ${FUNCTION_DIR} -RUN npm install - - -# Stage 3 - final runtime image -# Grab a fresh copy of the Node image -FROM node-amazonlinux - -# Required for Node runtimes which use npm@8.6.0+ because -# by default npm writes logs under /home/.npm and Lambda fs is read-only -ENV NPM_CONFIG_CACHE=/tmp/.npm -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Set working directory to function root directory -WORKDIR ${FUNCTION_DIR} -# Copy in the built dependencies -COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} - -ENTRYPOINT [ "/usr/bin/npx", "aws-lambda-ric" ] -CMD [ "index.handler" ] diff --git a/test/integration/docker/Dockerfile.echo.centos b/test/integration/docker/Dockerfile.echo.centos deleted file mode 100644 index 778b5560..00000000 --- a/test/integration/docker/Dockerfile.echo.centos +++ /dev/null @@ -1,68 +0,0 @@ -# Define global args -ARG FUNCTION_DIR="/home/app/" -ARG RUNTIME_VERSION -ARG DISTRO_VERSION - -# Stage 1 - bundle base image + runtime -# Grab a fresh copy of the image and install Node -FROM quay.io/centos/centos:${DISTRO_VERSION} AS node-centos -# Include global arg in this stage of the build -ARG RUNTIME_VERSION -# Install NodeJS -RUN yum module enable -y nodejs:${RUNTIME_VERSION} && \ - yum install -y nodejs - - -# Stage 2 - build function and dependencies -FROM node-centos AS build-image -ARG ARCHITECTURE -# Install aws-lambda-cpp build dependencies -RUN yum install -y \ - tar \ - gzip \ - make \ - wget \ - autoconf \ - automake \ - libtool \ - libcurl-devel \ - gcc-c++ -# Install a modern CMake -RUN wget --quiet -O cmake-install https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0-linux-${ARCHITECTURE}.sh && \ - sh cmake-install --skip-license --prefix=/usr --exclude-subdirectory; - -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Create function directory -RUN mkdir -p ${FUNCTION_DIR} - -# Copy & build Runtime Interface Client package (as we're installing it from a local filesystem source) -WORKDIR ${FUNCTION_DIR}/deps/aws-lambda-ric -COPY . . - -RUN make build && \ - npm run test:unit - -# Copy function code -COPY test/integration/test-handlers/echo/* ${FUNCTION_DIR} -# Install the function's dependencies -WORKDIR ${FUNCTION_DIR} -RUN npm install - - -# Stage 3 - final runtime image -# Grab a fresh copy of the Node image -FROM node-centos - -# Required for Node runtimes which use npm@8.6.0+ because -# by default npm writes logs under /home/.npm and Lambda fs is read-only -ENV NPM_CONFIG_CACHE=/tmp/.npm -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Set working directory to function root directory -WORKDIR ${FUNCTION_DIR} -# Copy in the built dependencies -COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} - -ENTRYPOINT [ "/usr/bin/npx", "aws-lambda-ric" ] -CMD [ "index.handler" ] diff --git a/test/integration/docker/Dockerfile.echo.debian b/test/integration/docker/Dockerfile.echo.debian deleted file mode 100644 index a611d8f3..00000000 --- a/test/integration/docker/Dockerfile.echo.debian +++ /dev/null @@ -1,50 +0,0 @@ -# Define global args -ARG FUNCTION_DIR="/home/app/" -ARG RUNTIME_VERSION -ARG DISTRO_VERSION - -# Stage 1 - build function and dependencies -FROM node:${RUNTIME_VERSION}-${DISTRO_VERSION} AS build-image -# Install aws-lambda-cpp build dependencies -RUN apt-get update && \ - apt-get install -y \ - g++ \ - make \ - cmake \ - libcurl4-openssl-dev - -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Create function directory -RUN mkdir -p ${FUNCTION_DIR} - -# Copy & build Runtime Interface Client package (as we're installing it from a local filesystem source) -WORKDIR ${FUNCTION_DIR}/deps/aws-lambda-ric -COPY . . - -RUN make build && \ - npm run test:unit - -# Copy function code -COPY test/integration/test-handlers/echo/* ${FUNCTION_DIR} -# Install the function's dependencies -WORKDIR ${FUNCTION_DIR} -RUN npm install - - -# Stage 2 - final runtime image -# Grab a fresh slim copy of the Node image -FROM node:${RUNTIME_VERSION}-${DISTRO_VERSION}-slim - -# Required for Node runtimes which use npm@8.6.0+ because -# by default npm writes logs under /home/.npm and Lambda fs is read-only -ENV NPM_CONFIG_CACHE=/tmp/.npm -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Set working directory to function root directory -WORKDIR ${FUNCTION_DIR} -# Copy in the built dependencies -COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} - -ENTRYPOINT [ "/usr/local/bin/npx", "aws-lambda-ric" ] -CMD [ "index.handler" ] diff --git a/test/integration/docker/Dockerfile.echo.ubuntu b/test/integration/docker/Dockerfile.echo.ubuntu deleted file mode 100644 index 567768bf..00000000 --- a/test/integration/docker/Dockerfile.echo.ubuntu +++ /dev/null @@ -1,77 +0,0 @@ -# Define global args -ARG FUNCTION_DIR="/home/app/" -ARG RUNTIME_VERSION -ARG DISTRO_VERSION - -# Stage 1 - bundle base image + runtime -# Grab a fresh copy of the image and install Node -FROM ubuntu:${DISTRO_VERSION} AS node-ubuntu -# Non-interactive mode -ENV DEBIAN_FRONTEND=noninteractive -# Install NodeJS -ARG RUNTIME_VERSION -RUN apt-get update && \ - apt-get install -y \ - curl && \ - curl -sL https://deb.nodesource.com/setup_${RUNTIME_VERSION}.x | bash - && \ - apt-get install -y nodejs - - -# Stage 2 - build function and dependencies -FROM node-ubuntu AS build-image -ARG ARCHITECTURE -# Install aws-lambda-cpp build dependencies -RUN apt-get update && \ - apt-get install -y \ - g++ \ - gcc \ - tar \ - curl \ - gzip \ - make \ - cmake \ - autoconf \ - automake \ - libtool \ - wget \ - libcurl4-openssl-dev \ - python3 -# Install a modern CMake -RUN wget --quiet -O cmake-install https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0-linux-${ARCHITECTURE}.sh && \ - sh cmake-install --skip-license --prefix=/usr --exclude-subdirectory; - -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Create function directory -RUN mkdir -p ${FUNCTION_DIR} - -# Copy & build Runtime Interface Client package (as we're installing it from a local filesystem source) -WORKDIR ${FUNCTION_DIR}/deps/aws-lambda-ric -COPY . . - -RUN make build && \ - npm run test:unit - -# Copy function code -COPY test/integration/test-handlers/echo/* ${FUNCTION_DIR} -# Install the function's dependencies -WORKDIR ${FUNCTION_DIR} -RUN npm install - - -# Stage 3 - final runtime image -# Grab a fresh copy of the Node image -FROM node-ubuntu - -# Required for Node runtimes which use npm@8.6.0+ because -# by default npm writes logs under /home/.npm and Lambda fs is read-only -ENV NPM_CONFIG_CACHE=/tmp/.npm -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Set working directory to function root directory -WORKDIR ${FUNCTION_DIR} -# Copy in the built dependencies -COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} - -ENTRYPOINT [ "/usr/bin/npx", "aws-lambda-ric" ] -CMD [ "index.handler" ] diff --git a/test/integration/docker/Dockerfile.programmatic.alpine b/test/integration/docker/Dockerfile.programmatic.alpine deleted file mode 100644 index 5bcb4b7b..00000000 --- a/test/integration/docker/Dockerfile.programmatic.alpine +++ /dev/null @@ -1,67 +0,0 @@ -# Define global args -ARG FUNCTION_DIR="/home/app/" -ARG RUNTIME_VERSION -ARG DISTRO_VERSION - -# Stage 1 - build function and dependencies -FROM node:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} AS build-image -# Include global arg in this stage of the build -ARG DISTRO_VERSION -# Install aws-lambda-cpp build dependencies -RUN apk add --update-cache \ - build-base \ - libtool \ - musl-dev \ - libressl-dev \ - libffi-dev \ - autoconf \ - automake \ - make \ - cmake \ - python3 \ - libcurl - -# AWS Lambda CPP and libcurl rely on backtrace which requires libexecinfo from Alpine. -# Since starting from Alpine3.17 libexecinfo is no longer available, temporarily source it from Alpine3.16 -# while awaiting an upstream resolution in AWS Lambda CPP. -RUN if [[ "${DISTRO_VERSION}" == "3.17" ]] || [[ "${DISTRO_VERSION}" == "3.18" ]] ; \ -then \ - apk add --update-cache --repository=https://dl-cdn.alpinelinux.org/alpine/v3.16/main/ libexecinfo-dev ; \ -else \ - apk add --update-cache libexecinfo-dev ; \ -fi - -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Create function directory -RUN mkdir -p ${FUNCTION_DIR} - -# Copy & build Runtime Interface Client package (as we're installing it from a local filesystem source) -WORKDIR ${FUNCTION_DIR}/deps/aws-lambda-ric -COPY . . - -RUN make build && \ - npm run test:unit - -# Copy function code -COPY test/integration/test-handlers/programmatic/* ${FUNCTION_DIR} -# Install the function's dependencies -WORKDIR ${FUNCTION_DIR} -RUN npm install - - -# Stage 2 - final runtime image -# Grab a fresh copy of the Node image -FROM node:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} - -# Required for Node runtimes which use npm@8.6.0+ because -# by default npm writes logs under /home/.npm and Lambda fs is read-only -ENV NPM_CONFIG_CACHE=/tmp/.npm -# Include global arg in this stage of the build -ARG FUNCTION_DIR -# Set working directory to function root directory -WORKDIR ${FUNCTION_DIR} -# Copy in the built dependencies -COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} - -CMD [ "/usr/local/bin/node", "index.mjs" ] diff --git a/test/integration/resources/aws-lambda-rie-arm64.tar.gz b/test/integration/resources/aws-lambda-rie-arm64.tar.gz deleted file mode 100644 index 57878e2b..00000000 Binary files a/test/integration/resources/aws-lambda-rie-arm64.tar.gz and /dev/null differ diff --git a/test/integration/resources/aws-lambda-rie.tar.gz b/test/integration/resources/aws-lambda-rie.tar.gz deleted file mode 100644 index 2553eaa3..00000000 Binary files a/test/integration/resources/aws-lambda-rie.tar.gz and /dev/null differ diff --git a/test/integration/test-handlers/echo/index.js b/test/integration/test-handlers/echo/index.js deleted file mode 100644 index ff988d38..00000000 --- a/test/integration/test-handlers/echo/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -exports.handler = async (event, context) => { - console.log('hello world'); - return 'success'; -}; diff --git a/test/integration/test-handlers/echo/package.json b/test/integration/test-handlers/echo/package.json deleted file mode 100644 index 7d320212..00000000 --- a/test/integration/test-handlers/echo/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "echo-hanlder", - "version": "1.0.0", - "description": "Sample Lambda echo handler for NodeJS", - "author": "AWS Lambda", - "license": "Apache-2.0", - "dependencies": { - "aws-lambda-ric": "file:deps/aws-lambda-ric" - } -} diff --git a/test/integration/test-handlers/programmatic/index.mjs b/test/integration/test-handlers/programmatic/index.mjs deleted file mode 100644 index 8d3d85a5..00000000 --- a/test/integration/test-handlers/programmatic/index.mjs +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -import { run } from 'aws-lambda-ric'; - -const echo = async (event, context) => { - console.log('hello world'); - return 'success'; -}; - -await run(echo); diff --git a/test/integration/test-handlers/programmatic/package.json b/test/integration/test-handlers/programmatic/package.json deleted file mode 100644 index 95b0c3f3..00000000 --- a/test/integration/test-handlers/programmatic/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "programmatic-hanlder", - "version": "1.0.0", - "description": "Sample Lambda echo handler for NodeJS", - "author": "AWS Lambda", - "license": "Apache-2.0", - "dependencies": { - "aws-lambda-ric": "file:deps/aws-lambda-ric" - } -} diff --git a/test/unit/ErrorsTest.js b/test/unit/ErrorsTest.js index 8f88ae62..ea98fd19 100644 --- a/test/unit/ErrorsTest.js +++ b/test/unit/ErrorsTest.js @@ -1,6 +1,4 @@ -/** - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - */ +/** Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ 'use strict'; @@ -22,11 +20,22 @@ describe('Formatted Error Logging', () => { describe('Invalid chars in HTTP header', () => { it('should be replaced', () => { - let errorWithInvalidChar = new Error('\x7F \x7F'); + let errorWithInvalidChar = new Error('\x7F'); errorWithInvalidChar.name = 'ErrorWithInvalidChar'; let loggedError = Errors.toRapidResponse(errorWithInvalidChar); loggedError.should.have.property('errorType', 'ErrorWithInvalidChar'); - loggedError.should.have.property('errorMessage', '%7F %7F'); + loggedError.should.have.property('errorMessage', '%7F'); + }); +}); + +describe('NodeJsExit error ctor', () => { + it('should be have a fixed reason', () => { + let nodeJsExit = new Errors.NodeJsExit(); + let loggedError = Errors.toRapidResponse(nodeJsExit); + loggedError.should.have.property('errorType', 'Runtime.NodeJsExit'); + loggedError.errorMessage.should.containEql( + 'runtime client detected an unexpected Node.js', + ); }); }); diff --git a/test/unit/InvokeContextTest.js b/test/unit/InvokeContextTest.js index c351b5d2..e0d6bfd3 100644 --- a/test/unit/InvokeContextTest.js +++ b/test/unit/InvokeContextTest.js @@ -35,3 +35,32 @@ describe('Getting remaining invoke time', () => { remainingTime.should.lessThanOrEqual(1000); }); }); + +describe('Verifying tenant id', () => { + it('should return undefined if tenant id is not set', () => { + let ctx = new InvokeContext({}); + + (ctx._headerData().tenantId === undefined).should.be.true(); + }); + it('should return undefined if tenant id is set to undefined', () => { + let ctx = new InvokeContext({ + 'lambda-runtime-aws-tenant-id': undefined, + }); + + (ctx._headerData().tenantId === undefined).should.be.true(); + }); + it('should return empty if tenant id is set to empty string', () => { + let ctx = new InvokeContext({ + 'lambda-runtime-aws-tenant-id': '', + }); + + (ctx._headerData().tenantId === '').should.be.true(); + }); + it('should return the same id if a valid tenant id is set', () => { + let ctx = new InvokeContext({ + 'lambda-runtime-aws-tenant-id': 'blue', + }); + + ctx._headerData().tenantId.should.equal('blue'); + }); +}); diff --git a/test/unit/IsAsyncTest.js b/test/unit/IsAsyncTest.js new file mode 100644 index 00000000..a4df41ae --- /dev/null +++ b/test/unit/IsAsyncTest.js @@ -0,0 +1,37 @@ +/** Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ + +'use strict'; + +require('should'); +const path = require('path'); +const UserFunction = require('lambda-runtime/UserFunction.js'); + +const TEST_ROOT = path.join(__dirname, '../'); +const HANDLERS_ROOT = path.join(TEST_ROOT, 'handlers'); + +describe('isAsync tests', () => { + it('is async should be true', async () => { + const handlerFunc = await UserFunction.load( + HANDLERS_ROOT, + 'isAsync.handlerAsync', + ); + const metadata = UserFunction.getHandlerMetadata(handlerFunc); + metadata.isAsync.should.be.true(); + }); + it('is async should be false', async () => { + const handlerFunc = await UserFunction.load( + HANDLERS_ROOT, + 'isAsync.handlerNotAsync', + ); + const metadata = UserFunction.getHandlerMetadata(handlerFunc); + metadata.isAsync.should.be.false(); + }); + it('is async should be false since it is a callback', async () => { + const handlerFunc = await UserFunction.load( + HANDLERS_ROOT, + 'isAsyncCallback.handler', + ); + const metadata = UserFunction.getHandlerMetadata(handlerFunc); + metadata.isAsync.should.be.false(); + }); +}); \ No newline at end of file diff --git a/test/unit/LogPatchTest.js b/test/unit/LogPatchTest.js index 7a8d2f6f..8cadb5b0 100644 --- a/test/unit/LogPatchTest.js +++ b/test/unit/LogPatchTest.js @@ -415,9 +415,38 @@ describe('The multiline log patch', () => { ); receivedMessage.should.have.property('level', logFunctions[fIdx][1]); receivedMessage.should.have.property('requestId', EXPECTED_ID); + receivedMessage.should.not.have.property('tenantId'); } }); + it('should format messages with tenant id as json correctly', () => { + const EXPECTED_TENANT_ID = 'tenantId'; + LogPatch.setCurrentTenantId(EXPECTED_TENANT_ID); + + for (let fIdx = 0; fIdx < logFunctions.length; fIdx++) { + logFunctions[fIdx][0]('structured logging with tenant id'); + let receivedMessage = telemetryTarget.readLine( + logFunctions[fIdx][1], + 'JSON', + ); + receivedMessage = JSON.parse(receivedMessage); + + receivedMessage.should.have.property('timestamp'); + let receivedTime = new Date(receivedMessage.timestamp); + let now = new Date(); + assert(now >= receivedTime && now - receivedTime <= 1000); + + receivedMessage.should.have.property( + 'message', + 'structured logging with tenant id', + ); + receivedMessage.should.have.property('level', logFunctions[fIdx][1]); + receivedMessage.should.have.property('requestId', EXPECTED_ID); + receivedMessage.should.have.property('tenantId', EXPECTED_TENANT_ID); + } + LogPatch.setCurrentTenantId(undefined); + }); + it('should filter messages correctly', () => { const loglevelSettings = [ undefined, diff --git a/test/unit/RAPIDClientTest.js b/test/unit/RAPIDClientTest.js index 828bd6de..a5851c0e 100644 --- a/test/unit/RAPIDClientTest.js +++ b/test/unit/RAPIDClientTest.js @@ -47,6 +47,23 @@ class NoOpNativeHttp { } } +class MockNativeClient { + constructor(response) { + this.response = response; + this.called = false; + this.shouldThrowError = false; + } + + next() { + this.called = true; + if (this.shouldThrowError) { + return Promise.reject(new Error('Failed to get next invocation')); + } else { + return Promise.resolve(this.response); + } + } +} + class EvilError extends Error { get name() { throw 'gotcha'; @@ -115,3 +132,82 @@ describe('invalid request id works', () => { }); }); }); + +describe('next invocation with native client works', () => { + it('should call the native client next() method', async () => { + const mockNative = new MockNativeClient({ + bodyJson: '', + headers: { + 'lambda-runtime-aws-request-id': 'test-request-id', + }, + }); + const client = new RAPIDClient('notUsed:1337', undefined, mockNative); + client.useAlternativeClient = false; + + await client.nextInvocation(); + // verify native client was called + mockNative.called.should.be.true(); + }); + it('should parse all required headers', async () => { + const mockResponse = { + bodyJson: '{"message":"Hello from Lambda!"}', + headers: { + 'lambda-runtime-aws-request-id': 'test-request-id', + 'lambda-runtime-deadline-ms': 1619712000000, + 'lambda-runtime-trace-id': 'test-trace-id', + 'lambda-runtime-invoked-function-arn': 'test-function-arn', + 'lambda-runtime-client-context': '{"client":{"app_title":"MyApp"}}', + 'lambda-runtime-cognito-identity': + '{"identityId":"id123","identityPoolId":"pool123"}', + 'lambda-runtime-aws-tenant-id': 'test-tenant-id', + }, + }; + + const mockNative = new MockNativeClient(mockResponse); + const client = new RAPIDClient('notUsed:1337', undefined, mockNative); + + client.useAlternativeClient = false; + const response = await client.nextInvocation(); + + // Verify all headers are present + response.headers.should.have.property( + 'lambda-runtime-aws-request-id', + 'test-request-id', + ); + response.headers.should.have.property( + 'lambda-runtime-deadline-ms', + 1619712000000, + ); + response.headers.should.have.property( + 'lambda-runtime-trace-id', + 'test-trace-id', + ); + response.headers.should.have.property( + 'lambda-runtime-invoked-function-arn', + 'test-function-arn', + ); + response.headers.should.have.property( + 'lambda-runtime-client-context', + '{"client":{"app_title":"MyApp"}}', + ); + response.headers.should.have.property( + 'lambda-runtime-cognito-identity', + '{"identityId":"id123","identityPoolId":"pool123"}', + ); + response.headers.should.have.property( + 'lambda-runtime-aws-tenant-id', + 'test-tenant-id', + ); + // Verify body is correctly passed through + response.bodyJson.should.equal('{"message":"Hello from Lambda!"}'); + }); + it('should handle native client errors', async () => { + const nativeClient = new MockNativeClient({}); + nativeClient.shouldThrowError = true; + + const client = new RAPIDClient('localhost:8080', null, nativeClient); + client.useAlternativeClient = false; + + await client.nextInvocation().should.be.rejectedWith('Failed to get next invocation'); + }); +}); diff --git a/test/unit/WarningForCallbackHandlersTest.js b/test/unit/WarningForCallbackHandlersTest.js new file mode 100644 index 00000000..82398390 --- /dev/null +++ b/test/unit/WarningForCallbackHandlersTest.js @@ -0,0 +1,68 @@ +/* +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +'use strict'; + +require('should'); + +let { captureStream, consoleSnapshot } = require('./LoggingGlobals'); + +let { + checkForDeprecatedCallback, +} = require('../../src/WarningForCallbackHandlers.js'); + +let LogPatch = require('lambda-runtime/LogPatch'); +const UserFunction = require('lambda-runtime/UserFunction.js'); + +const path = require('path'); +const TEST_ROOT = path.join(__dirname, '../'); +const HANDLERS_ROOT = path.join(TEST_ROOT, 'handlers'); + +describe('Formatted Error Logging', () => { + let restoreConsole = consoleSnapshot(); + let capturedStdout = captureStream(process.stdout); + + beforeEach( + 'delete env var', + () => delete process.env.AWS_LAMBDA_NODEJS_DISABLE_CALLBACK_WARNING, + ); + beforeEach('capture stdout', () => capturedStdout.hook()); + beforeEach('apply console patch', () => LogPatch.patchConsole()); + afterEach('remove console patch', () => restoreConsole()); + afterEach('unhook stdout', () => capturedStdout.unhook()); + + const expectedString = + 'AWS Lambda plans to remove support for callback-based function handlers'; + + const tests = [ + { args: [false, 'isAsyncCallback.handler'], expected: true }, + { args: [true, 'isAsyncCallback.handler'], expected: false }, + { args: [false, 'isAsync.handlerAsync'], expected: false }, + { args: [true, 'isAsync.handlerAsync'], expected: false }, + { args: [false, 'defaultHandler.default'], expected: false }, + { args: [true, 'defaultHandler.default'], expected: false }, + ]; + + tests.forEach(({ args, expected }) => { + const shouldDeclareEnv = args[0]; + const handler = args[1]; + it(`When AWS_LAMBDA_NODEJS_DISABLE_CALLBACK_WARNING=${shouldDeclareEnv} expecting ${ + expected ? 'no ' : '' + }warning logs for handler ${handler}`, async () => { + if (shouldDeclareEnv) { + process.env.AWS_LAMBDA_NODEJS_DISABLE_CALLBACK_WARNING = 1; + } + const handlerFunc = await UserFunction.load(HANDLERS_ROOT, handler); + const metadata = UserFunction.getHandlerMetadata(handlerFunc); + + checkForDeprecatedCallback(metadata); + if (expected) { + capturedStdout.captured().should.containEql(expectedString); + } else { + capturedStdout.captured().should.not.containEql(expectedString); + } + }); + }); +}); \ No newline at end of file