diff --git a/.eslintignore b/.eslintignore index 542b5b51..40b5bbe7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ test/mock scratch/ +*-vendor.js diff --git a/.github/workflows/binary-build.yml b/.github/workflows/binary-build.yml index b86aa5c3..0901f7e6 100644 --- a/.github/workflows/binary-build.yml +++ b/.github/workflows/binary-build.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node-version: [ 14.x ] + node-version: [ 16.x ] os: [ windows-latest, ubuntu-latest, macOS-latest ] # Go @@ -37,7 +37,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: '2.7' + ruby-version: '3.2' - name: Set up Deno uses: denolib/setup-deno@v2 @@ -74,7 +74,7 @@ jobs: - name: Notify uses: sarisia/actions-status-discord@v1 # Only fire alert once - if: github.ref == 'refs/heads/main' && failure() && matrix.node-version == '14.x' && matrix.os == 'ubuntu-latest' + if: github.ref == 'refs/heads/main' && failure() && matrix.node-version == '20.x' && matrix.os == 'ubuntu-latest' with: webhook: ${{ secrets.DISCORD_WEBHOOK }} title: "build and test" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1196b92a..ae357569 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node-version: [ 14.x, 16.x, 18.x ] + node-version: [ 16.x, 18.x, 20.x ] os: [ windows-latest, ubuntu-latest, macOS-latest ] # Go @@ -68,7 +68,7 @@ jobs: - name: Notify uses: sarisia/actions-status-discord@v1 # Only fire alert once - if: github.ref == 'refs/heads/main' && failure() && matrix.node-version == '14.x' && matrix.os == 'ubuntu-latest' + if: github.ref == 'refs/heads/main' && failure() && matrix.node-version == '20.x' && matrix.os == 'ubuntu-latest' with: webhook: ${{ secrets.DISCORD_WEBHOOK }} title: "build and test" @@ -92,7 +92,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v3 with: - node-version: 16 + node-version: lts/* registry-url: https://registry.npmjs.org/ # Publish to npm diff --git a/.gitignore b/.gitignore index 5ea826a2..c8ff8638 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ __pycache__ !test/mock/dep-warn/**/node_modules .DS_Store .nyc_output/ +*-vendor.js bin/*.json bin/sandbox-binary* chonky.txt diff --git a/bin/binary-config.js b/bin/binary-config.js index bc510666..460611a2 100644 --- a/bin/binary-config.js +++ b/bin/binary-config.js @@ -22,7 +22,8 @@ let config = { '../node_modules/**/@architect/inventory/**/*.js', ], assets: [ - '../src/invoke-lambda/exec/runtimes/*' + '../src/invoke-lambda/exec/runtimes/*', + '../src/tables/_aws-lite-dynamodb-vendor.js', ], targets: [], outputPath: 'bin' diff --git a/changelog.md b/changelog.md index cc5da2e5..dd39341c 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,19 @@ --- +## [6.0.0] 2024-01-09 + +### Changed + +- Transitioned from `aws-sdk` to [`aws-lite`](https://aws-lite.org) +- Breaking change: Sandbox no longer includes `aws-sdk` + `@aws-sdk/*` as dependencies; projects that rely on the AWS SDK should install those dependencies to their project directly +- Breaking change: `nodejs20.x` and `python3.12` are now the default Node.js and Python Lambda runtimes, respectively +- Breaking change: removed support for Node.js 14.x (now EOL, and no longer available to created in AWS Lambda) +- Added Node.js 20.x to test matrix +- Updated dependencies + +--- + ## [5.9.4] 2023-11-20 ### Changed diff --git a/package.json b/package.json index 2d00134f..d4e89e82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@architect/sandbox", - "version": "5.9.4", + "version": "6.0.0-RC.4", "description": "Architect dev server: run full Architect projects locally & offline", "main": "src/index.js", "scripts": { @@ -10,7 +10,7 @@ "coverage": "nyc --reporter=lcov --reporter=text npm run test:unit", "lint": "eslint . --fix", "rc": "npm version prerelease --preid RC", - "build": "node bin/binary-config.js && npx pkg bin" + "build": "node scripts/vendor.js && node bin/binary-config.js && npx pkg bin" }, "engines": { "node": ">=14" @@ -28,21 +28,14 @@ "src/*" ], "dependencies": { - "@architect/asap": "~6.0.4", - "@architect/create": "~4.2.4", - "@architect/hydrate": "~3.5.1", - "@architect/inventory": "~3.6.3", - "@architect/utils": "~3.1.9", - "@aws-sdk/client-apigatewaymanagementapi": "^3.316.0", - "@aws-sdk/client-dynamodb": "^3.316.0", - "@aws-sdk/client-s3": "^3.316.0", - "@aws-sdk/client-sns": "^3.316.0", - "@aws-sdk/client-sqs": "^3.316.0", - "@aws-sdk/client-ssm": "^3.316.0", - "@aws-sdk/lib-dynamodb": "^3.316.0", - "@aws-sdk/node-http-handler": "^3.360.0", + "@architect/asap": "~7.0.0", + "@architect/create": "~5.0.0", + "@architect/hydrate": "~4.0.0", + "@architect/inventory": "~4.0.0", + "@architect/utils": "~4.0.0", + "@aws-lite/client": "^0.15.2", + "@aws-lite/dynamodb": "^0.3.3", "@begin/hashid": "~1.0.0", - "aws-sdk": "^2.1363.0", "chalk": "4.1.2", "chokidar": "~3.5.3", "depstatus": "~1.1.1", @@ -50,7 +43,7 @@ "finalhandler": "~1.2.0", "glob": "~10.3.10", "http-proxy": "~1.18.1", - "lambda-runtimes": "~1.1.6", + "lambda-runtimes": "~2.0.1", "minimist": "~1.2.8", "router": "~1.3.8", "run-parallel": "~1.2.0", @@ -60,20 +53,22 @@ "tmp": "~0.2.1", "tree-kill": "~1.2.2", "update-notifier-cjs": "~5.1.6", - "ws": "~8.14.2" + "ws": "~8.16.0" }, "devDependencies": { "@architect/eslint-config": "~2.1.2", - "@architect/functions": "~7.0.0", + "@architect/functions": "~8.0.0-RC.3", "@architect/req-res-fixtures": "git+https://github.com/architect/req-res-fixtures.git", + "@aws-lite/apigatewaymanagementapi": "~0.0.7", + "@aws-lite/ssm": "~0.2.2", "cross-env": "~7.0.3", - "eslint": "~8.54.0", - "fs-extra": "~11.1.1", + "eslint": "~8.56.0", + "fs-extra": "~11.2.0", "nyc": "~15.1.0", "pkg": "~5.8.1", "proxyquire": "~2.1.3", "tap-arc": "~1.2.2", - "tape": "~5.7.2", + "tape": "~5.7.4", "tiny-json-http": "~7.5.1" }, "eslintConfig": { diff --git a/scripts/.npmrc b/scripts/.npmrc new file mode 100644 index 00000000..43c97e71 --- /dev/null +++ b/scripts/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/scripts/aws-lite-dynamodb.mjs b/scripts/aws-lite-dynamodb.mjs new file mode 100644 index 00000000..38a8df3b --- /dev/null +++ b/scripts/aws-lite-dynamodb.mjs @@ -0,0 +1,4 @@ +import dynamo from '@aws-lite/dynamodb' +export const service = dynamo.service +export const property = dynamo.property +export const methods = dynamo.methods diff --git a/scripts/package.json b/scripts/package.json new file mode 100644 index 00000000..b57623f9 --- /dev/null +++ b/scripts/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "esbuild": "^0.19.5" + } +} diff --git a/scripts/vendor.js b/scripts/vendor.js new file mode 100644 index 00000000..23c2fb30 --- /dev/null +++ b/scripts/vendor.js @@ -0,0 +1,8 @@ +#! /usr/bin/env node + +let { execSync } = require('child_process') +let cwd = __dirname +let options = { cwd, stdio: 'inherit' } + +execSync('npm install --force --omit=dev', options) +execSync('npx esbuild ./aws-lite-dynamodb.mjs --bundle --platform=node --format=cjs --outfile=../src/tables/_aws-lite-dynamodb-vendor.js', options) diff --git a/scripts/vendor.sh b/scripts/vendor.sh new file mode 100755 index 00000000..bd32e841 --- /dev/null +++ b/scripts/vendor.sh @@ -0,0 +1,5 @@ +cd scripts + +npm install --force --omit=dev + +npx esbuild ./aws-lite-dynamodb.mjs --bundle --platform=node --format=cjs --outfile=../src/tables/_aws-lite-dynamodb-vendor.js diff --git a/src/arc/_ssm/index.js b/src/arc/_ssm/index.js index fb2c86bc..20b1563a 100644 --- a/src/arc/_ssm/index.js +++ b/src/arc/_ssm/index.js @@ -101,6 +101,7 @@ module.exports = function _ssm ({ body, services }, params, req, res) { update.verbose.warn(err) res.statusCode = 400 error = error || { __type: 'InternalServerError', message: 'Unknown Sandbox error: ' + err.stack } + res.setHeader('content-type', 'application/json') res.end(JSON.stringify(error)) return } diff --git a/src/cli/arc.js b/src/cli/arc.js index 7baeb401..d0e43861 100644 --- a/src/cli/arc.js +++ b/src/cli/arc.js @@ -7,9 +7,8 @@ let cli = require('./index.js') module.exports = function arcCalling ({ inventory }) { cli({ disableBanner: true, - needsValidCreds: false, - runtimeCheck: 'warn', inventory, + runtimeCheck: 'warn', }, function _done (err) { if (err) { diff --git a/src/http/middleware/_fallback.js b/src/http/middleware/_fallback.js index 9bc39e5c..567f0919 100644 --- a/src/http/middleware/_fallback.js +++ b/src/http/middleware/_fallback.js @@ -12,7 +12,7 @@ let httpProxy = require('http-proxy') * - Error out */ module.exports = function fallback (args, req, res, next) { - let { apiType, cwd, inventory, ports, staticPath, update } = args + let { apiType, creds, cwd, inventory, ports, staticPath, update } = args let { inv, get } = inventory let httpAPI = apiType.startsWith('http') let method = req.method.toLowerCase() @@ -111,6 +111,7 @@ module.exports = function fallback (args, req, res, next) { let name = `${rootParam[0]} /${rootParam[1]}` let lambda = get.http(name) let exec = invoker({ + creds, cwd, lambda, apiType, @@ -144,6 +145,7 @@ module.exports = function fallback (args, req, res, next) { function invokeProxy (src, arcStaticAssetProxy) { let exec = invoker({ apiType, + creds, cwd, lambda: { name: 'get /*', diff --git a/src/invoke-lambda/env/index.js b/src/invoke-lambda/env/index.js index aa09dfea..8cced7d7 100644 --- a/src/invoke-lambda/env/index.js +++ b/src/invoke-lambda/env/index.js @@ -5,10 +5,11 @@ let { version } = require('../../../package.json') // Assemble Lambda-specific execution environment variables module.exports = function getEnv (params, requestID) { - let { apiType, cwd, lambda, host, inventory, ports, staticPath } = params + let { apiType, creds, cwd, lambda, host, inventory, ports, staticPath } = params + let { accessKeyId, secretAccessKey, sessionToken } = creds let { config, src, build, handlerFile } = lambda let { inv } = inventory - let { AWS_ACCESS_KEY_ID, AWS_PROFILE, AWS_REGION, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, PATH } = process.env + let { AWS_PROFILE, AWS_REGION, PATH } = process.env let lambdaContext = getContext(params) let envVars = userEnvVars(params) @@ -23,7 +24,7 @@ module.exports = function getEnv (params, requestID) { // Runtime environment variables let env = { // AWS-specific - AWS_ACCESS_KEY_ID, + AWS_ACCESS_KEY_ID: accessKeyId, AWS_LAMBDA_FUNCTION_MEMORY_SIZE: lambda.config.memory, AWS_LAMBDA_FUNCTION_NAME: `@${lambda.pragma} ${lambda.name}`, AWS_LAMBDA_FUNCTION_VERSION: '$latest', @@ -31,8 +32,8 @@ module.exports = function getEnv (params, requestID) { AWS_PROFILE, AWS_REGION, AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE: true, // Sigh. - AWS_SECRET_ACCESS_KEY, - AWS_SESSION_TOKEN, + AWS_SECRET_ACCESS_KEY: secretAccessKey, + AWS_SESSION_TOKEN: sessionToken, LAMBDA_TASK_ROOT: src, TZ: 'UTC', // Internal for handler bootstrap diff --git a/src/sandbox/creds.js b/src/sandbox/creds.js new file mode 100644 index 00000000..2ffcf78e --- /dev/null +++ b/src/sandbox/creds.js @@ -0,0 +1,25 @@ +let awsLite = require('@aws-lite/client') +module.exports = function loadCreds (params, callback) { + let { inventory } = params + awsLite({ + autoloadPlugins: false, + profile: inventory.inv?.aws?.profile, + region: 'us-west-1', // Region doesn't matter, we just need to get creds + }) + .then(aws => { + params.creds = { + // secretAccessKey + sessionToken are non-enumerable, so we can't just ref or spread + accessKeyId: aws.credentials.accessKeyId, + secretAccessKey: aws.credentials.secretAccessKey, + sessionToken: aws.credentials.sessionToken, + } + callback() + }) + .catch(() => { + params.creds = { + accessKeyId: 'arc_dummy_access_key', + secretAccessKey: 'arc_dummy_secret_key', + } + callback() + }) +} diff --git a/src/sandbox/index.js b/src/sandbox/index.js index 1896fd8a..d330b344 100644 --- a/src/sandbox/index.js +++ b/src/sandbox/index.js @@ -3,6 +3,7 @@ let series = require('run-series') let create = require('@architect/create') let env = require('./env') +let creds = require('./creds') let ports = require('./ports') let checkRuntimes = require('./check-runtimes') let maybeHydrate = require('./maybe-hydrate') @@ -27,6 +28,11 @@ function _start (params, callback) { env(params, callback) }, + // Load credentials + function (callback) { + creds(params, callback) + }, + // Get the ports for services function (callback) { ports(params, callback) @@ -107,12 +113,7 @@ function _start (params, callback) { ], function (err) { if (err) callback(err) - else { - if (process.env.ARC_AWS_CREDS === 'dummy' && !restart) { - update.verbose.warn('Missing or invalid AWS credentials or credentials file, using dummy credentials (this is probably ok)') - } - callback(null, params.ports) - } + else callback(null, params.ports) }) } diff --git a/src/sandbox/seed.js b/src/sandbox/seed.js index a07a7721..770f9b59 100644 --- a/src/sandbox/seed.js +++ b/src/sandbox/seed.js @@ -5,7 +5,7 @@ let getDBClient = require('../tables/_get-db-client') module.exports = function startupSeedData (params, callback) { let { ARC_ENV } = process.env - let { cwd, inventory, update, ports } = params + let { creds, cwd, inventory, update, ports } = params let { inv, get } = inventory let { app, tables } = inv if (!tables || ARC_ENV !== 'testing') return callback() @@ -47,13 +47,17 @@ module.exports = function startupSeedData (params, callback) { return } let TableName = `${app}-staging-${table}` - return rows.map(Item => callback => dynamo.put({ TableName, Item }, callback)) + return rows.map(Item => callback => { + dynamo.PutItem({ TableName, Item }) + .then(result => callback(null, result)) + .catch(callback) + }) }).filter(Boolean) - getDBClient(ports, (err, db, doc) => { + getDBClient({ creds, inventory, ports }, (err, aws) => { if (err) callback(err) else { - dynamo = doc + dynamo = aws.DynamoDB let start = Date.now() series(seeds, (err) => { if (err) callback(err) diff --git a/src/tables/_get-db-client.js b/src/tables/_get-db-client.js index b3882b17..233b3ed0 100644 --- a/src/tables/_get-db-client.js +++ b/src/tables/_get-db-client.js @@ -1,41 +1,22 @@ -// eslint-disable-next-line -try { require('aws-sdk/lib/maintenance_mode_message').suppress = true } -catch { /* Noop */ } -let aws = require('aws-sdk') - -module.exports = function initDynamoClient (ports, callback) { - /** - * Final DynamoDB credentials backstop - * - Creds are usually loaded for the process via banner's AWS initialization routines - * - Assumes that aws.config.credentials is present if aws-sdk successfully loaded valid credentials - * - Populate AWS-specific env vars necessary to mock Lambda + make SDK calls if not already loaded - * - Only AWS_SECRET_ACCESS_KEY + AWS_ACCESS_KEY_ID are technically required to mock Lambda - */ - let creds = aws.config.credentials - - // Fail loudly and early if a creds file is present without a default profile - if (Array.isArray(creds) && !creds.length) { - let msg = `AWS credentials file found without a 'default' profile; you must add a default profile, specify a different profile, or remove your credentials file` - return callback(ReferenceError(msg)) - } - - if (!process.env.AWS_ACCESS_KEY_ID && creds?.accessKeyId) { - process.env.AWS_ACCESS_KEY_ID = creds.accessKeyId - } - if (!process.env.AWS_SECRET_ACCESS_KEY && creds?.secretAccessKey) { - process.env.AWS_SECRET_ACCESS_KEY = creds.secretAccessKey - } - if (!creds) { - // These env vars *should* already be instantiated by utils >= 1.4.7 – but do it jic! - process.env.AWS_SECRET_ACCESS_KEY = 'xxx' - process.env.AWS_ACCESS_KEY_ID = 'xxx' - } +let { join } = require('path') +let awsLite = require('@aws-lite/client') +module.exports = function initDynamoClient ({ creds, inventory, ports }, callback) { + let plugins = [ + // Binary dist mode + process.pkg + ? join(__dirname, '_aws-lite-dynamodb-vendor.js') + : '@aws-lite/dynamodb' + ] let config = { + autoloadPlugins: false, endpoint: `http://localhost:${ports.tables}`, - region: process.env.AWS_REGION || 'us-west-2', + plugins, + profile: inventory.inv?.aws?.profile, + region: inventory.inv?.aws?.region || process.env.AWS_REGION || 'us-west-2', + ...creds, } - let dynamo = new aws.DynamoDB(config) - let document = new aws.DynamoDB.DocumentClient(config) - callback(null, dynamo, document) + awsLite(config) + .then(client => callback(null, client)) + .catch(callback) } diff --git a/src/tables/_init.js b/src/tables/_init.js index b464bf04..11b5b263 100644 --- a/src/tables/_init.js +++ b/src/tables/_init.js @@ -1,23 +1,10 @@ -let createTable = require('./create-table') let getDBClient = require('./_get-db-client') -let series = require('run-series') +let createTables = require('./create-table') -module.exports = function init ({ inventory, ports }, callback) { - getDBClient(ports, function _gotDBClient (err, dynamo) { - if (err) { - return callback(err) - } - - let { inv } = inventory - let app = inv.app - - // User tables (and their indexes) - let plans = inv.tables.map(table => { - return function (callback) { - createTable({ app, dynamo, inventory, ports, table }, callback) - } - }) - - series(plans, callback) +// Just a thin passthrough to enable the abstraction of getDBClient (for testing) +module.exports = function init ({ creds, inventory, ports }, callback) { + getDBClient({ creds, inventory, ports }, (err, aws) => { + if (err) return callback(err) + createTables({ aws, inventory, ports }, callback) }) } diff --git a/src/tables/create-table/_create-table.js b/src/tables/create-table/_create-table.js index f2fa9bb9..4bbe0112 100644 --- a/src/tables/create-table/_create-table.js +++ b/src/tables/create-table/_create-table.js @@ -3,42 +3,42 @@ let getKeySchema = require('./_get-key-schema') let getGSI = require('./_get-global-secondary-index') module.exports = function _createTable (params, callback) { - let { name, TableName, dynamo, inventory, ports, table } = params + let { table, TableName, aws, inventory, ports } = params + let { name } = table - dynamo.listTables({}, function _tables (err, result) { - if (err) { + aws.DynamoDB.ListTables({}) + .then(result => { + let found = result.TableNames.find(tbl => tbl === TableName) + if (found) return callback() + + let creating = { + TableName, + AttributeDefinitions: getAttributeDefinitions(params), + KeySchema: getKeySchema(table), + ProvisionedThroughput: { + ReadCapacityUnits: 5, + WriteCapacityUnits: 5 + } + } + // Handle global secondary index stuff + let gsi = getGSI({ name, inventory }) + if (gsi) creating.GlobalSecondaryIndexes = gsi + + aws.DynamoDB.CreateTable(creating) + .then(result => callback(null, result)) + .catch(callback) + }) + .catch(err => { console.log(err) if (err.message === 'socket hang up' && err.name === 'TimeoutError') { let msg = `Sandbox was unable to instantiate database tables on port ${ports.tables} due to a timeout error\n` + - `This has been known to occur when system emulators (or tools that use them) attempt to use port ${ports.tables}\n` + - `Please ensure you are not running any such emulators or tools, or manually specify a different @tables port, and try starting Sandbox again` + `This has been known to occur when system emulators (or tools that use them) attempt to use port ${ports.tables}\n` + + `Please ensure you are not running any such emulators or tools, or manually specify a different @tables port, and try starting Sandbox again` console.log(msg) process.exit(1) } let msg = 'Unable to list DynamoDB tables' throw Error(msg) - } - else { - let found = result.TableNames.find(tbl => tbl === TableName) - if (found) callback() - else { - let creating = { - TableName, - AttributeDefinitions: getAttributeDefinitions(params), - KeySchema: getKeySchema(table), - ProvisionedThroughput: { - ReadCapacityUnits: 5, - WriteCapacityUnits: 5 - } - } - - // Handle global secondary index stuff - let gsi = getGSI({ name, inventory }) - if (gsi) creating.GlobalSecondaryIndexes = gsi - - dynamo.createTable(creating, callback) - } - } - }) + }) } diff --git a/src/tables/create-table/_get-attribute-definitions.js b/src/tables/create-table/_get-attribute-definitions.js index c1d8a430..3bfdee4f 100644 --- a/src/tables/create-table/_get-attribute-definitions.js +++ b/src/tables/create-table/_get-attribute-definitions.js @@ -1,5 +1,6 @@ module.exports = function getAttributeDefinitions (params) { - let { name, inventory, table, oob } = params + let { table, inventory, oob } = params + let { name } = table let { get } = inventory // oob is Sandbox default tables; otherwise it's userland diff --git a/src/tables/create-table/index.js b/src/tables/create-table/index.js index 3dc5cca5..ca36684a 100644 --- a/src/tables/create-table/index.js +++ b/src/tables/create-table/index.js @@ -1,3 +1,4 @@ +let series = require('run-series') let parallel = require('run-parallel') let create = require('./_create-table') @@ -6,24 +7,30 @@ let create = require('./_create-table') * @param params.app String * @param params.table Object */ -module.exports = function createTable (params, callback) { - let { app, table } = params - let { name } = table +module.exports = function createTables (params, callback) { + let { inventory } = params + let { inv } = inventory + let app = inv.app - parallel([ - function _createStaging (callback) { - create({ - name, - TableName: `${app}-staging-${name}`, - ...params - }, callback) - }, - function _createProduction (callback) { - create({ - name, - TableName: `${app}-production-${name}`, - ...params + // User tables (and their indexes) + let plans = inv.tables.map(table => { + return function (callback) { + parallel({ + staging: (callback) => { + create({ + TableName: `${app}-staging-${table.name}`, + table, ...params + }, callback) + }, + production: (callback) => { + create({ + TableName: `${app}-production-${table.name}`, + table, ...params + }, callback) + } }, callback) } - ], callback) + }) + + series(plans, callback) } diff --git a/test/integration/arc/ssm-test.js b/test/integration/arc/ssm-test.js index 54b13f75..d4301076 100644 --- a/test/integration/arc/ssm-test.js +++ b/test/integration/arc/ssm-test.js @@ -1,8 +1,6 @@ -require('aws-sdk/lib/maintenance_mode_message').suppress = true let { join } = require('path') let test = require('tape') -let aws = require('aws-sdk') -let http = require('http') +let awsLite = require('@aws-lite/client') let sut = join(process.cwd(), 'src') let sandbox = require(sut) let { credentials, run, startup, shutdown } = require('../../utils') @@ -10,11 +8,7 @@ let _arcPort = 2222 let app = 'MockappTesting' let tables = [ 'accounts', 'pets', 'places', 'data' ] - -// AWS services to test -let endpoint = new aws.Endpoint(`http://localhost:${_arcPort}/_arc/ssm`) -let httpOptions = { agent: new http.Agent() } -let ssm = new aws.SSM({ endpoint, region: 'us-west-2', httpOptions, credentials }) +let ssm function check ({ result, type, items, fallback, t }) { let internal = result.Parameters?.[0]?.Name?.includes('ARC_SANDBOX') ? 1 : 0 @@ -30,9 +24,16 @@ function check ({ result, type, items, fallback, t }) { }) } -test('Set up env', t => { - t.plan(1) +test('Set up env', async t => { + t.plan(2) t.ok(sandbox, 'Got Sandbox') + let aws = await awsLite({ + ...credentials, + endpoint: `http://localhost:${_arcPort}/_arc/ssm`, + region: 'us-west-2', + }) + ssm = aws.SSM + t.ok(ssm, 'Populated SSM client') }) test('Run internal Arc SSM service tests', t => { @@ -50,165 +51,134 @@ function runTests (runType, t) { /** * ssm.getParametersByPath() */ - t.test(`${mode} Get & check params (without specifying a type)`, t => { + t.test(`${mode} Get & check params (without specifying a type)`, async t => { t.plan(6) // Should get all tables params back - ssm.getParametersByPath({ Path: `/${app}` }, function (err, result) { - if (err) t.end(err) - else { - t.equal(result.Parameters.length, 5, 'Got back correct number of params') - check({ result, type: 'tables', items: tables, t }) - } - }) + let result = await ssm.GetParametersByPath({ Path: `/${app}` }) + t.equal(result.Parameters.length, 5, 'Got back correct number of params') + check({ result, type: 'tables', items: tables, t }) }) - t.test(`${mode} Get & check params (without specifying a type; Arc Functions bare module mode)`, t => { + t.test(`${mode} Get & check params (without specifying a type; Arc Functions bare module mode)`, async t => { t.plan(6) // Should get all tables params back - ssm.getParametersByPath({ Path: `/ArcAppTesting` }, function (err, result) { - if (err) t.end(err) - else { - t.equal(result.Parameters.length, 5, 'Got back correct number of params') - check({ result, type: 'tables', items: tables, fallback: true, t }) - } - }) + let result = await ssm.GetParametersByPath({ Path: `/ArcAppTesting` }) + t.equal(result.Parameters.length, 5, 'Got back correct number of params') + check({ result, type: 'tables', items: tables, fallback: true, t }) }) - t.test(`${mode} Get & check params (specifying a type)`, t => { + t.test(`${mode} Get & check params (specifying a type)`, async t => { t.plan(6) - ssm.getParametersByPath({ Path: `/${app}/tables` }, function (err, result) { - if (err) t.end(err) - else { - t.equal(result.Parameters.length, 4, 'Got back correct number of params') - check({ result, type: 'tables', items: tables, t }) - } - }) + let result = await ssm.GetParametersByPath({ Path: `/${app}/tables` }) + t.equal(result.Parameters.length, 4, 'Got back correct number of params') + check({ result, type: 'tables', items: tables, t }) }) - t.test(`${mode} Get & check params (specifying a type; Arc Functions bare module mode)`, t => { + t.test(`${mode} Get & check params (specifying a type; Arc Functions bare module mode)`, async t => { t.plan(6) - ssm.getParametersByPath({ Path: `/ArcAppTesting/tables` }, function (err, result) { - if (err) t.end(err) - else { - t.equal(result.Parameters.length, 4, 'Got back correct number of params') - check({ result, type: 'tables', items: tables, fallback: true, t }) - } - }) + let result = await ssm.GetParametersByPath({ Path: `/ArcAppTesting/tables` }) + check({ result, type: 'tables', items: tables, fallback: true, t }) + t.equal(result.Parameters.length, 4, 'Got back correct number of params') }) - t.test(`${mode} Get & check params (specifying an invalid or unknown service)`, t => { + t.test(`${mode} Get & check params (specifying an invalid or unknown service)`, async t => { t.plan(1) - ssm.getParametersByPath({ Path: `/${app}/idk` }, function (err, result) { - if (err) t.end(err) - else t.deepEqual(result.Parameters, [], 'No parameters returned') - }) + let result = await ssm.GetParametersByPath({ Path: `/${app}/idk` }) + t.deepEqual(result.Parameters, [], 'No parameters returned') }) - t.test(`${mode} Get & check params (specifying an invalid or unknown service; Arc Functions bare module mode)`, t => { + t.test(`${mode} Get & check params (specifying an invalid or unknown service; Arc Functions bare module mode)`, async t => { t.plan(1) - ssm.getParametersByPath({ Path: `/ArcAppTesting/idk` }, function (err, result) { - if (err) t.end(err) - else t.deepEqual(result.Parameters, [], 'No parameters returned') - }) + let result = await ssm.GetParametersByPath({ Path: `/ArcAppTesting/idk` }) + t.deepEqual(result.Parameters, [], 'No parameters returned') }) - t.test(`${mode} Get & check params (specifying an invalid or unknown app)`, t => { + t.test(`${mode} Get & check params (specifying an invalid or unknown app)`, async t => { t.plan(1) - ssm.getParametersByPath({ Path: `/idk` }, function (err, result) { - if (err) t.end(err) - else t.deepEqual(result.Parameters, [], 'No parameters returned') - }) + let result = await ssm.GetParametersByPath({ Path: `/idk` }) + t.deepEqual(result.Parameters, [], 'No parameters returned') }) - t.test(`${mode} Get & check params (specifying an unknown app + known service)`, t => { + t.test(`${mode} Get & check params (specifying an unknown app + known service)`, async t => { t.plan(1) - ssm.getParametersByPath({ Path: `/idk/tables` }, function (err, result) { - if (err) t.end(err) - else t.deepEqual(result.Parameters, [], 'No parameters returned') - }) + let result = await ssm.GetParametersByPath({ Path: `/idk/tables` }) + t.deepEqual(result.Parameters, [], 'No parameters returned') }) /** * ssm.getParameter() */ - t.test(`${mode} Get & check a param`, t => { + t.test(`${mode} Get & check a param`, async t => { t.plan(1) let key = `/${app}/tables/accounts` - ssm.getParameter({ Name: key }, function (err, result) { - if (err) t.end(err) - else { - let { Name, Value } = result.Parameter - if (Name === key && Value === `mockapp-staging-accounts`) { - t.pass(`Found param: ${key}`) - } - else t.end(`Could not find param: ${key}`) - } - }) + let result = await ssm.GetParameter({ Name: key }) + let { Name, Value } = result.Parameter + if (Name === key && Value === `mockapp-staging-accounts`) { + t.pass(`Found param: ${key}`) + } + else t.end(`Could not find param: ${key}`) }) - t.test(`${mode} Get & check a param (Arc Functions bare module mode)`, t => { + t.test(`${mode} Get & check a param (Arc Functions bare module mode)`, async t => { t.plan(1) let key = `/ArcAppTesting/tables/accounts` - ssm.getParameter({ Name: key }, function (err, result) { - if (err) t.end(err) - else { - let { Name, Value } = result.Parameter - if (Name === key && Value === `mockapp-staging-accounts`) { - t.pass(`Found param: ${key}`) - } - else t.end(`Could not find param: ${key}`) - } - }) + let result = await ssm.GetParameter({ Name: key }) + let { Name, Value } = result.Parameter + if (Name === key && Value === `mockapp-staging-accounts`) { + t.pass(`Found param: ${key}`) + } + else t.end(`Could not find param: ${key}`) }) - t.test(`${mode} Getting a param without specifying a service type should fail`, t => { - t.plan(2) + t.test(`${mode} Getting a param without specifying a service type should fail`, async t => { + t.plan(1) let key = `/${app}` - ssm.getParameter({ Name: key }, function (err) { - if (!err) t.fail('Expected error') - else { - t.match(err.name, /ParameterNotFound/, 'Got ParameterNotFound error') - t.equal(err.message, null, 'Returned null value') - } - }) + try { + await ssm.GetParameter({ Name: key }) + t.fail('Expected an error') + } + catch (err) { + t.match(err.__type, /ParameterNotFound/, 'Got ParameterNotFound error') + } }) - t.test(`${mode} Getting a param without specifying a param should fail`, t => { - t.plan(2) + t.test(`${mode} Getting a param without specifying a param should fail`, async t => { + t.plan(1) let key = `/${app}/tables/idk` - ssm.getParameter({ Name: key }, function (err) { - if (!err) t.fail('Expected error') - else { - t.match(err.name, /ParameterNotFound/, 'Got ParameterNotFound error') - t.equal(err.message, null, 'Returned null value') - } - }) + try { + await ssm.GetParameter({ Name: key }) + t.fail('Expected an error') + } + catch (err) { + t.match(err.__type, /ParameterNotFound/, 'Got ParameterNotFound error') + } }) - t.test(`${mode} Getting a param without specifying a param should fail (trailing slash)`, t => { + t.test(`${mode} Getting a param without specifying a param should fail (trailing slash)`, async t => { t.plan(2) let key = `/${app}/tables/` - ssm.getParameter({ Name: key }, function (err) { - if (!err) t.fail('Expected error') - else { - t.match(err.name, /ValidationException/, 'Got ValidationException error') - t.match(err.message, /Parameter cannot end in \'\/\'/, 'Errored on trailing slash') - } - }) + try { + await ssm.GetParameter({ Name: key }) + t.fail('Expected an error') + } + catch (err) { + t.match(err.__type, /ValidationException/, 'Got ValidationException error') + t.match(err.message, /Parameter cannot end in \'\/\'/, 'Errored on trailing slash') + } }) /** * Fail on unsupported ssm methods */ - t.test(`${mode} Get & check params (without specifying a type)`, t => { - t.plan(2) - ssm.getParameters({ Names: [ 'a', 'b' ] }, function (err) { - if (!err) t.fail('Expected error') - else { - t.match(err.name, /InternalServerError/, 'Got InternalServerError error') - t.match(err.message, /Unrecognized request, Sandbox only supports/, 'Tried to provide a helpful error') - } - }) + t.test(`${mode} Get & check params (without specifying a type)`, async t => { + t.plan(1) + try { + await ssm.GetParameters({ Names: [ 'a', 'b' ] }) + t.fail('Expected an error') + } + catch (err) { + t.match(err.message, /Unrecognized request, Sandbox only supports/, 'Tried to provide a helpful error') + } }) t.test(`${mode} Shut down Sandbox`, t => { @@ -219,19 +189,15 @@ function runTests (runType, t) { startup[runType](t, 'plugins-sync') }) - t.test(`${mode} Get & check params provided by plugin (without specifying a type)`, t => { + t.test(`${mode} Get & check params provided by plugin (without specifying a type)`, async t => { t.plan(5) // Should get all tables params back - ssm.getParametersByPath({ Path: '/PluginsSandboxTesting' }, function (err, result) { - if (err) t.end(err) - else { - t.equal(result.Parameters.length, 2, 'One parameter returned') - t.equal(result.Parameters[0].Name, '/PluginsSandboxTesting/ARC_SANDBOX/ports', 'Plugin parameter name correct') - t.match(result.Parameters[0].Value, /\"_arc\":/, 'Plugin parameter value correct') - t.equal(result.Parameters[1].Name, '/PluginsSandboxTesting/myplugin/varOne', 'Plugin parameter name correct') - t.equal(result.Parameters[1].Value, 'valueOne', 'Plugin parameter value correct') - } - }) + let result = await ssm.GetParametersByPath({ Path: '/PluginsSandboxTesting' }) + t.equal(result.Parameters.length, 2, 'One parameter returned') + t.equal(result.Parameters[0].Name, '/PluginsSandboxTesting/ARC_SANDBOX/ports', 'Plugin parameter name correct') + t.match(result.Parameters[0].Value, /\"_arc\":/, 'Plugin parameter value correct') + t.equal(result.Parameters[1].Name, '/PluginsSandboxTesting/myplugin/varOne', 'Plugin parameter name correct') + t.equal(result.Parameters[1].Value, 'valueOne', 'Plugin parameter value correct') }) t.test(`${mode} Shut down Sandbox`, t => { diff --git a/test/integration/arc/ws-test.js b/test/integration/arc/ws-test.js index e59fb385..597e7476 100644 --- a/test/integration/arc/ws-test.js +++ b/test/integration/arc/ws-test.js @@ -1,17 +1,21 @@ -require('aws-sdk/lib/maintenance_mode_message').suppress = true let { join } = require('path') let test = require('tape') -let aws = require('aws-sdk') -let http = require('http') +let awsLite = require('@aws-lite/client') let Websocket = require('ws') let sut = join(process.cwd(), 'src') let sandbox = require(sut) let { credentials, run, startup, shutdown, makeSideChannel, wsUrl } = require('../../utils') let _arcPort = 2222 +let ApiUrl = `http://localhost:${_arcPort}/_arc/ws` +let apiGatewayManagementApi + test('Set up env', async t => { - t.plan(1) + t.plan(2) t.ok(sandbox, 'Got Sandbox') + let aws = await awsLite({ ...credentials, region: 'us-west-2', keepAlive: false }) + apiGatewayManagementApi = aws.ApiGatewayManagementApi + t.ok(apiGatewayManagementApi, 'Populated ApiGatewayManagementApi client') }) test('Run internal Arc API Gateway Management service tests', t => { @@ -25,11 +29,6 @@ function runTests (runType, t) { let _ws let ConnectionId - // AWS services to test - let endpoint = new aws.Endpoint(`http://localhost:${_arcPort}/_arc/ws`) - let httpOptions = { agent: new http.Agent() } - let apiGatewayManagementApi = new aws.ApiGatewayManagementApi({ endpoint, region: 'us-west-2', httpOptions, credentials }) - let connectWebSocket = async () => { if (_ws) throw Error('Only one websocket can be connected at a time, test is not clean') _ws = new Websocket(wsUrl) @@ -72,7 +71,7 @@ function runTests (runType, t) { ConnectionId = connectionEvent.event.requestContext.connectionId t.ok(ConnectionId, `Got requestContext with connectionId: ${ConnectionId}`) - let connection = await apiGatewayManagementApi.getConnection({ ConnectionId }).promise() + let connection = await apiGatewayManagementApi.GetConnection({ ApiUrl, ConnectionId }) t.ok(new Date(Date.parse(connection.ConnectedAt)) <= new Date(), `Got back connectedAt string: ${connection.ConnectedAt}`) }) @@ -80,25 +79,23 @@ function runTests (runType, t) { t.plan(1) let Data = JSON.stringify({ message: 'hi' }) let messagePromise = new Promise(resolve => _ws.once('message', resolve)) - await apiGatewayManagementApi.postToConnection({ ConnectionId, Data }).promise() + await apiGatewayManagementApi.PostToConnection({ ApiUrl, ConnectionId, Data }) const message = (await messagePromise).toString() - // console.log({ message }) t.equals(message, Data, 'Got message') }) t.test(`${mode} Disconnect a socket`, async t => { - t.plan(3) + t.plan(2) let closePromise = new Promise(resolve => _ws.once('close', resolve)) - await apiGatewayManagementApi.deleteConnection({ ConnectionId }).promise() + await apiGatewayManagementApi.DeleteConnection({ ApiUrl, ConnectionId }) await closePromise t.notOk(_ws, 'WebSocket closed') try { - await apiGatewayManagementApi.getConnection({ ConnectionId }).promise() + await apiGatewayManagementApi.GetConnection({ ApiUrl, ConnectionId }) t.fail('getConnection should have thrown') } catch (error) { - t.equals(error.message, '410', 'Error message matches') - t.equals(error.code, 'GoneException', 'Error Code Matches') + t.equals(error.statusCode, 410, 'Error status matches') } }) diff --git a/test/integration/http/http-test.js b/test/integration/http/http-test.js index 4dd4a8e5..2992e638 100644 --- a/test/integration/http/http-test.js +++ b/test/integration/http/http-test.js @@ -166,17 +166,17 @@ function runTests (runType, t) { }) }) - t.test(`${mode} get /nodejs18.x`, t => { + t.test(`${mode} get /nodejs20.x`, t => { t.plan(15) - let rawPath = '/nodejs18.x' + let rawPath = '/nodejs20.x' tiny.get({ url: url + rawPath }, function _got (err, result) { if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /nodejs18.x (running nodejs18.x)', - routeKey: 'GET /nodejs18.x', + message: 'Hello from get /nodejs20.x (running nodejs20.x)', + routeKey: 'GET /nodejs20.x', rawPath, pathParameters: undefined, cookies: undefined, @@ -190,17 +190,17 @@ function runTests (runType, t) { }) }) - t.test(`${mode} get /nodejs14.x`, t => { + t.test(`${mode} get /nodejs18.x`, t => { t.plan(15) - let rawPath = '/nodejs14.x' + let rawPath = '/nodejs18.x' tiny.get({ url: url + rawPath }, function _got (err, result) { if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /nodejs14.x (running nodejs14.x)', - routeKey: 'GET /nodejs14.x', + message: 'Hello from get /nodejs18.x (running nodejs18.x)', + routeKey: 'GET /nodejs18.x', rawPath, pathParameters: undefined, cookies: undefined, @@ -238,9 +238,9 @@ function runTests (runType, t) { }) }) - t.test(`${mode} get /python3.8`, t => { + t.test(`${mode} get /python3.11`, t => { t.plan(16) - let rawPath = '/python3.8' + let rawPath = '/python3.11' tiny.get({ url: url + rawPath }, function _got (err, result) { @@ -248,8 +248,8 @@ function runTests (runType, t) { else if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /python3.8 (running python3.8)', - routeKey: 'GET /python3.8', + message: 'Hello from get /python3.11 (running python3.11)', + routeKey: 'GET /python3.11', rawPath, pathParameters: undefined, cookies: undefined, @@ -260,7 +260,7 @@ function runTests (runType, t) { body: undefined, context: { aws_request_id: true, // Just check for presence - function_name: 'sandbox-get-python3_8', + function_name: 'sandbox-get-python3_11', function_version: '$LATEST', invoked_function_arn: 'sandbox', memory_limit_in_mb: 1152, @@ -270,9 +270,9 @@ function runTests (runType, t) { }) }) - t.test(`${mode} get /python3.7`, t => { - t.plan(15) - let rawPath = '/python3.7' + t.test(`${mode} get /python3.8`, t => { + t.plan(16) + let rawPath = '/python3.8' tiny.get({ url: url + rawPath }, function _got (err, result) { @@ -280,8 +280,8 @@ function runTests (runType, t) { else if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /python3.7 (running python3.7)', - routeKey: 'GET /python3.7', + message: 'Hello from get /python3.8 (running python3.8)', + routeKey: 'GET /python3.8', rawPath, pathParameters: undefined, cookies: undefined, @@ -290,22 +290,29 @@ function runTests (runType, t) { headers: '🤷🏽‍♀️', isBase64Encoded: false, body: undefined, + context: { + aws_request_id: true, // Just check for presence + function_name: 'sandbox-get-python3_8', + function_version: '$LATEST', + invoked_function_arn: 'sandbox', + memory_limit_in_mb: 1152, + } }) } }) }) - t.test(`${mode} get /ruby2.7`, t => { + t.test(`${mode} get /ruby3.2`, t => { t.plan(16) - let rawPath = '/ruby2.7' + let rawPath = '/ruby3.2' tiny.get({ url: url + rawPath }, function _got (err, result) { if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /ruby2.7 (running ruby2.7)', - routeKey: 'GET /ruby2.7', + message: 'Hello from get /ruby3.2 (running ruby3.2)', + routeKey: 'GET /ruby3.2', rawPath, pathParameters: undefined, cookies: undefined, @@ -316,7 +323,7 @@ function runTests (runType, t) { body: undefined, context: { aws_request_id: true, // Just check for presence - function_name: 'sandbox-get-ruby2_7', + function_name: 'sandbox-get-ruby3_2', function_version: '$LATEST', invoked_function_arn: 'sandbox', memory_limit_in_mb: 1152, diff --git a/test/integration/http/httpv1-test.js b/test/integration/http/httpv1-test.js index ac3a2eb5..36cf57f6 100644 --- a/test/integration/http/httpv1-test.js +++ b/test/integration/http/httpv1-test.js @@ -128,16 +128,16 @@ function runTests (runType, t) { }) }) - t.test(`${mode} get /nodejs18.x`, t => { + t.test(`${mode} get /nodejs20.x`, t => { t.plan(16) - let path = '/nodejs18.x' + let path = '/nodejs20.x' tiny.get({ url: url + path }, function _got (err, result) { if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /nodejs18.x (running nodejs18.x)', + message: 'Hello from get /nodejs20.x (running nodejs20.x)', resource: path, path, httpMethod: 'GET', @@ -153,16 +153,16 @@ function runTests (runType, t) { }) }) - t.test(`${mode} get /nodejs14.x`, t => { + t.test(`${mode} get /nodejs18.x`, t => { t.plan(16) - let path = '/nodejs14.x' + let path = '/nodejs18.x' tiny.get({ url: url + path }, function _got (err, result) { if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /nodejs14.x (running nodejs14.x)', + message: 'Hello from get /nodejs18.x (running nodejs18.x)', resource: path, path, httpMethod: 'GET', @@ -203,9 +203,9 @@ function runTests (runType, t) { }) }) - t.test(`${mode} get /python3.8`, t => { + t.test(`${mode} get /python3.11`, t => { t.plan(17) - let path = '/python3.8' + let path = '/python3.11' tiny.get({ url: url + path }, function _got (err, result) { @@ -213,7 +213,7 @@ function runTests (runType, t) { else if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /python3.8 (running python3.8)', + message: 'Hello from get /python3.11 (running python3.11)', resource: path, path, httpMethod: 'GET', @@ -226,7 +226,7 @@ function runTests (runType, t) { isBase64Encoded: false, context: { aws_request_id: true, // Just check for presence - function_name: 'sandbox-get-python3_8', + function_name: 'sandbox-get-python3_11', function_version: '$LATEST', invoked_function_arn: 'sandbox', memory_limit_in_mb: 1152, @@ -235,10 +235,9 @@ function runTests (runType, t) { } }) }) - - t.test(`${mode} get /python3.7`, t => { - t.plan(16) - let path = '/python3.7' + t.test(`${mode} get /python3.8`, t => { + t.plan(17) + let path = '/python3.8' tiny.get({ url: url + path }, function _got (err, result) { @@ -246,7 +245,7 @@ function runTests (runType, t) { else if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /python3.7 (running python3.7)', + message: 'Hello from get /python3.8 (running python3.8)', resource: path, path, httpMethod: 'GET', @@ -257,21 +256,28 @@ function runTests (runType, t) { pathParameters: null, body: null, isBase64Encoded: false, + context: { + aws_request_id: true, // Just check for presence + function_name: 'sandbox-get-python3_8', + function_version: '$LATEST', + invoked_function_arn: 'sandbox', + memory_limit_in_mb: 1152, + } }) } }) }) - t.test(`${mode} get /ruby2.7`, t => { + t.test(`${mode} get /ruby3.2`, t => { t.plan(17) - let path = '/ruby2.7' + let path = '/ruby3.2' tiny.get({ url: url + path }, function _got (err, result) { if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /ruby2.7 (running ruby2.7)', + message: 'Hello from get /ruby3.2 (running ruby3.2)', resource: path, path, httpMethod: 'GET', @@ -284,7 +290,7 @@ function runTests (runType, t) { isBase64Encoded: false, context: { aws_request_id: true, // Just check for presence - function_name: 'sandbox-get-ruby2_7', + function_name: 'sandbox-get-ruby3_2', function_version: '$LATEST', invoked_function_arn: 'sandbox', memory_limit_in_mb: 1152, diff --git a/test/integration/http/rest-test.js b/test/integration/http/rest-test.js index 747f0006..149bf9c6 100644 --- a/test/integration/http/rest-test.js +++ b/test/integration/http/rest-test.js @@ -128,16 +128,16 @@ function runTests (runType) { }) }) - test(`${mode} get /nodejs18.x`, t => { + test(`${mode} get /nodejs20.x`, t => { t.plan(16) - let path = '/nodejs18.x' + let path = '/nodejs20.x' tiny.get({ url: url + path }, function _got (err, result) { if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /nodejs18.x (running nodejs18.x)', + message: 'Hello from get /nodejs20.x (running nodejs20.x)', resource: path, path, httpMethod: 'GET', @@ -153,16 +153,16 @@ function runTests (runType) { }) }) - test(`${mode} get /nodejs14.x`, t => { + test(`${mode} get /nodejs18.x`, t => { t.plan(16) - let path = '/nodejs14.x' + let path = '/nodejs18.x' tiny.get({ url: url + path }, function _got (err, result) { if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /nodejs14.x (running nodejs14.x)', + message: 'Hello from get /nodejs18.x (running nodejs18.x)', resource: path, path, httpMethod: 'GET', @@ -178,9 +178,9 @@ function runTests (runType) { }) }) - test(`${mode} get /python3.8`, t => { + test(`${mode} get /python3.11`, t => { t.plan(17) - let path = '/python3.8' + let path = '/python3.11' tiny.get({ url: url + path }, function _got (err, result) { @@ -188,7 +188,7 @@ function runTests (runType) { else if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /python3.8 (running python3.8)', + message: 'Hello from get /python3.11 (running python3.11)', resource: path, path, httpMethod: 'GET', @@ -201,7 +201,7 @@ function runTests (runType) { isBase64Encoded: false, context: { aws_request_id: true, // Just check for presence - function_name: 'sandbox-get-python3_8', + function_name: 'sandbox-get-python3_11', function_version: '$LATEST', invoked_function_arn: 'sandbox', memory_limit_in_mb: 1152, @@ -211,9 +211,9 @@ function runTests (runType) { }) }) - test(`${mode} get /python3.7`, t => { - t.plan(16) - let path = '/python3.7' + test(`${mode} get /python3.8`, t => { + t.plan(17) + let path = '/python3.8' tiny.get({ url: url + path }, function _got (err, result) { @@ -221,7 +221,7 @@ function runTests (runType) { else if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /python3.7 (running python3.7)', + message: 'Hello from get /python3.8 (running python3.8)', resource: path, path, httpMethod: 'GET', @@ -232,21 +232,28 @@ function runTests (runType) { pathParameters: null, body: null, isBase64Encoded: false, + context: { + aws_request_id: true, // Just check for presence + function_name: 'sandbox-get-python3_8', + function_version: '$LATEST', + invoked_function_arn: 'sandbox', + memory_limit_in_mb: 1152, + } }) } }) }) - test(`${mode} get /ruby2.7`, t => { + test(`${mode} get /ruby3.2`, t => { t.plan(17) - let path = '/ruby2.7' + let path = '/ruby3.2' tiny.get({ url: url + path }, function _got (err, result) { if (err) t.end(err) else { checkResult(t, result.body, { - message: 'Hello from get /ruby2.7 (running ruby2.7)', + message: 'Hello from get /ruby3.2 (running ruby3.2)', resource: path, path, httpMethod: 'GET', @@ -259,7 +266,7 @@ function runTests (runType) { isBase64Encoded: false, context: { aws_request_id: true, // Just check for presence - function_name: 'sandbox-get-ruby2_7', + function_name: 'sandbox-get-ruby3_2', function_version: '$LATEST', invoked_function_arn: 'sandbox', memory_limit_in_mb: 1152, diff --git a/test/integration/tables-test.js b/test/integration/tables-test.js index 16bc155a..732f246a 100644 --- a/test/integration/tables-test.js +++ b/test/integration/tables-test.js @@ -6,7 +6,7 @@ let getDBClient = require(join(process.cwd(), 'src', 'tables', '_get-db-client') let TableName = 'mockapp-production-accounts' let TableName2 = 'mockapp-production-pets' let mock = join(process.cwd(), 'test', 'mock') -let { run, startup, shutdown } = require('../utils') +let { credentials: creds, run, startup, shutdown } = require('../utils') let str = s => JSON.stringify(s, null, 2) let dynamo let tablesPort = 5555 @@ -45,100 +45,76 @@ function runTests (runType, t) { t.test(`${mode} Get client`, t => { t.plan(1) - getDBClient(ports, function _gotDBClient (err, client) { + getDBClient({ creds, ports }, function _gotDBClient (err, client) { if (err) console.log(err) // Yes, but actually no - dynamo = client + dynamo = client.DynamoDB t.ok(dynamo, 'Got Dynamo client') }) }) - t.test(`${mode} Can list tables`, t => { + t.test(`${mode} Can list tables`, async t => { t.plan(1) setup(t) - dynamo.listTables({}, function done (err, result) { - if (err) t.end(err) - else { - let { TableNames } = result - t.ok(Array.isArray(TableNames), `Got tables back from the DB: ${TableNames}`) - teardown(t) - } - }) + let result = await dynamo.ListTables({}) + let { TableNames } = result + t.ok(Array.isArray(TableNames), `Got tables back from the DB: ${TableNames}`) + teardown(t) }) - t.test(`${mode} Can insert a row`, t => { + t.test(`${mode} Can insert a row`, async t => { t.plan(1) setup(t) - dynamo.putItem({ + let result = await dynamo.PutItem({ TableName, Item: { - accountID: { S: 'mock-account-id' }, - email: { S: 'person@email.lol' } - } - }, - function _put (err, result) { - if (err) t.end(err) - else { - t.ok(result, `Got result: ${str(result)}`) - teardown(t) + accountID: 'mock-account-id', + email: 'person@email.lol' } }) + t.ok(result, `Got result: ${str(result)}`) + teardown(t) }) - t.test(`${mode} Can read index in Arc 6`, t => { + t.test(`${mode} Can read index in Arc 6`, async t => { t.plan(1) setup(t) - dynamo.describeTable({ + let result = await dynamo.DescribeTable({ TableName - }, - function _desc (err, result) { - if (err) t.end(err) - else { - t.equal(result.Table.GlobalSecondaryIndexes[0].IndexName, 'email-index', 'Got index: email-index') - teardown(t) - } }) + t.equal(result.Table.GlobalSecondaryIndexes[0].IndexName, 'email-index', 'Got index: email-index') + teardown(t) }) - t.test(`${mode} Can read index in Arc 6`, t => { + t.test(`${mode} Can read index in Arc 6`, async t => { t.plan(3) setup(t) - dynamo.describeTable({ + let result = await dynamo.DescribeTable({ TableName: TableName2 - }, - function _desc (err, result) { - if (err) t.end(err) - else { - let indexes = result.Table.GlobalSecondaryIndexes - t.equal(indexes.length, 2, 'Got back two indexes') - t.equal(indexes[0].IndexName, 'petID-index', 'Got index: petID-index') - t.equal(indexes[1].IndexName, 'accountID-petID-index', 'Got index: accountID-petID-index') - teardown(t) - } }) + let indexes = result.Table.GlobalSecondaryIndexes + t.equal(indexes.length, 2, 'Got back two indexes') + t.equal(indexes[0].IndexName, 'petID-index', 'Got index: petID-index') + t.equal(indexes[1].IndexName, 'accountID-petID-index', 'Got index: accountID-petID-index') + teardown(t) }) - t.test(`${mode} Can read the row`, t => { + t.test(`${mode} Can read the row`, async t => { t.plan(1) setup(t) - dynamo.getItem({ + let result = await dynamo.GetItem({ TableName, Key: { - accountID: { S: 'fake-account-id' } - } - }, - function _desc (err, result) { - if (err) t.end(err) - else { - t.ok(result, `Got result: ${str(result)}`) - teardown(t) + accountID: 'fake-account-id' } }) + t.ok(result, `Got result: ${str(result)}`) + teardown(t) }) - t.test(`${mode} Can query the index`, t => { + t.test(`${mode} Can query the index`, async t => { t.plan(1) setup(t) - dynamo.query({ + let result = await dynamo.Query({ TableName, IndexName: 'email-index', KeyConditions: { @@ -147,14 +123,9 @@ function runTests (runType, t) { ComparisonOperator: 'EQ' } } - }, - function _desc (err, result) { - if (err) t.end(err) - else { - t.ok(result, `Got result: ${str(result)}`) - teardown(t) - } }) + t.ok(result, `Got result: ${str(result)}`) + teardown(t) }) t.test(`${mode} Shut down Sandbox`, t => { @@ -168,38 +139,26 @@ function runTests (runType, t) { startup[runType](t, join('seed-data', 'js'), { confirmStarted }) }) - t.test(`${mode} Scan seeded rows from first table`, t => { + t.test(`${mode} Scan seeded rows from first table`, async t => { t.plan(3) setup(t) - dynamo.scan({ TableName: 'seed-data-staging-stuff' }, - function _desc (err, result) { - if (err) t.end(err) - else { - console.log(str(result)) - t.equal(result.Count, 2, 'Got two results') - t.equal(result.Items[0].id.S, 'fiz', `Got expected row`) - t.equal(result.Items[1].id.S, 'foo', `Got expected row`) - teardown(t) - } - } - ) + let result = await dynamo.Scan({ TableName: 'seed-data-staging-stuff' }) + console.log(str(result)) + t.equal(result.Count, 2, 'Got two results') + t.equal(result.Items[0].id, 'fiz', `Got expected row`) + t.equal(result.Items[1].id, 'foo', `Got expected row`) + teardown(t) }) - t.test(`${mode} Scan seeded rows from second table`, t => { + t.test(`${mode} Scan seeded rows from second table`, async t => { t.plan(3) setup(t) - dynamo.scan({ TableName: 'seed-data-staging-things' }, - function _desc (err, result) { - if (err) t.end(err) - else { - console.log(str(result)) - t.equal(result.Count, 2, 'Got two results') - t.equal(result.Items[0].id.S, 'foo', `Got expected row`) - t.equal(result.Items[1].id.S, 'foo', `Got expected row`) - teardown(t) - } - } - ) + let result = await dynamo.Scan({ TableName: 'seed-data-staging-things' }) + console.log(str(result)) + t.equal(result.Count, 2, 'Got two results') + t.equal(result.Items[0].id, 'foo', `Got expected row`) + t.equal(result.Items[1].id, 'foo', `Got expected row`) + teardown(t) }) t.test(`${mode} Shut down Sandbox`, t => { @@ -210,38 +169,26 @@ function runTests (runType, t) { startup[runType](t, join('seed-data', 'json'), { confirmStarted }) }) - t.test(`${mode} Scan seeded rows from first table`, t => { + t.test(`${mode} Scan seeded rows from first table`, async t => { t.plan(3) setup(t) - dynamo.scan({ TableName: 'seed-data-staging-stuff' }, - function _desc (err, result) { - if (err) t.end(err) - else { - console.log(str(result)) - t.equal(result.Count, 2, 'Got two results') - t.equal(result.Items[0].id.S, 'fiz', `Got expected row`) - t.equal(result.Items[1].id.S, 'foo', `Got expected row`) - teardown(t) - } - } - ) + let result = await dynamo.Scan({ TableName: 'seed-data-staging-stuff' }) + console.log(str(result)) + t.equal(result.Count, 2, 'Got two results') + t.equal(result.Items[0].id, 'fiz', `Got expected row`) + t.equal(result.Items[1].id, 'foo', `Got expected row`) + teardown(t) }) - t.test(`${mode} Scan seeded rows from second table`, t => { + t.test(`${mode} Scan seeded rows from second table`, async t => { t.plan(3) setup(t) - dynamo.scan({ TableName: 'seed-data-staging-things' }, - function _desc (err, result) { - if (err) t.end(err) - else { - console.log(str(result)) - t.equal(result.Count, 2, 'Got two results') - t.equal(result.Items[0].id.S, 'foo', `Got expected row`) - t.equal(result.Items[1].id.S, 'foo', `Got expected row`) - teardown(t) - } - } - ) + let result = await dynamo.Scan({ TableName: 'seed-data-staging-things' }) + console.log(str(result)) + t.equal(result.Count, 2, 'Got two results') + t.equal(result.Items[0].id, 'foo', `Got expected row`) + t.equal(result.Items[1].id, 'foo', `Got expected row`) + teardown(t) }) t.test(`${mode} Shut down Sandbox`, t => { @@ -252,38 +199,26 @@ function runTests (runType, t) { startup[runType](t, join('seed-data', 'custom'), { confirmStarted }) }) - t.test(`${mode} Scan seeded rows from first table`, t => { + t.test(`${mode} Scan seeded rows from first table`, async t => { t.plan(3) setup(t) - dynamo.scan({ TableName: 'seed-data-staging-stuff' }, - function _desc (err, result) { - if (err) t.end(err) - else { - console.log(str(result)) - t.equal(result.Count, 2, 'Got two results') - t.equal(result.Items[0].id.S, 'fiz', `Got expected row`) - t.equal(result.Items[1].id.S, 'foo', `Got expected row`) - teardown(t) - } - } - ) + let result = await dynamo.Scan({ TableName: 'seed-data-staging-stuff' }) + console.log(str(result)) + t.equal(result.Count, 2, 'Got two results') + t.equal(result.Items[0].id, 'fiz', `Got expected row`) + t.equal(result.Items[1].id, 'foo', `Got expected row`) + teardown(t) }) - t.test(`${mode} Scan seeded rows from second table`, t => { + t.test(`${mode} Scan seeded rows from second table`, async t => { t.plan(3) setup(t) - dynamo.scan({ TableName: 'seed-data-staging-things' }, - function _desc (err, result) { - if (err) t.end(err) - else { - console.log(str(result)) - t.equal(result.Count, 2, 'Got two results') - t.equal(result.Items[0].id.S, 'foo', `Got expected row`) - t.equal(result.Items[1].id.S, 'foo', `Got expected row`) - teardown(t) - } - } - ) + let result = await dynamo.Scan({ TableName: 'seed-data-staging-things' }) + console.log(str(result)) + t.equal(result.Count, 2, 'Got two results') + t.equal(result.Items[0].id, 'foo', `Got expected row`) + t.equal(result.Items[1].id, 'foo', `Got expected row`) + teardown(t) }) t.test(`${mode} Shut down Sandbox`, t => { @@ -292,26 +227,22 @@ function runTests (runType, t) { t.test(`${mode} Start Sandbox`, t => { process.env.ARC_ENV = 'staging' + process.env.ARC_SANDBOX = '{}' // Force aws-lite to disable keepalive startup[runType](t, join('seed-data', 'js')) }) - t.test(`${mode} Data is not seeded when in !testing env`, t => { + t.test(`${mode} Data is not seeded when in !testing env`, async t => { t.plan(1) setup(t) - dynamo.scan({ TableName: 'seed-data-staging-stuff' }, - function _desc (err, result) { - if (err) t.end(err) - else { - console.log(str(result)) - t.equal(result.Count, 0, 'Got zero results') - teardown(t) - } - } - ) + let result = await dynamo.Scan({ TableName: 'seed-data-staging-stuff' }) + console.log(str(result)) + t.equal(result.Count, 0, 'Got zero results') + teardown(t) }) t.test(`${mode} Shut down Sandbox`, t => { delete process.env.ARC_ENV + delete process.env.ARC_SANDBOX shutdown[runType](t) }) @@ -336,25 +267,21 @@ function runTests (runType, t) { t.test(`${mode} Get client (external DB)`, t => { t.plan(1) setup(t, externalDBPort) - getDBClient({ tables: externalDBPort }, function _gotDBClient (err, client) { + getDBClient({ creds, ports: { tables: externalDBPort } }, function _gotDBClient (err, client) { if (err) console.log(err) // Yes, but actually no - dynamo = client + dynamo = client.DynamoDB t.ok(dynamo, 'Got Dynamo client') teardown(t) }) }) - t.test(`${mode} Can list tables (external DB)`, t => { + t.test(`${mode} Can list tables (external DB)`, async t => { t.plan(1) setup(t, externalDBPort) - dynamo.listTables({}, function done (err, result) { - if (err) t.end(err) - else { - let { TableNames } = result - t.ok(Array.isArray(TableNames), `Got tables back from the DB: ${TableNames}`) - teardown(t) - } - }) + let result = await dynamo.ListTables({}) + let { TableNames } = result + t.ok(Array.isArray(TableNames), `Got tables back from the DB: ${TableNames}`) + teardown(t) }) t.test(`${mode} Shut down Sandbox`, t => { diff --git a/test/mock/multi-handler/app.arc b/test/mock/multi-handler/app.arc index bc0fc06f..11b9f157 100644 --- a/test/mock/multi-handler/app.arc +++ b/test/mock/multi-handler/app.arc @@ -17,4 +17,4 @@ get /node/esm/index.js get /node/esm/index.mjs @arc -runtime nodejs14.x # The Deno functions have config files +runtime nodejs20.x # The Deno functions have config files diff --git a/test/mock/no-index-fail/src/http/get-foo/config.arc b/test/mock/no-index-fail/src/http/get-foo/config.arc index daf73a48..d9c37445 100644 --- a/test/mock/no-index-fail/src/http/get-foo/config.arc +++ b/test/mock/no-index-fail/src/http/get-foo/config.arc @@ -1,5 +1,5 @@ @aws -runtime nodejs14.x +runtime nodejs18.x # timeout 30 # concurrency 1 # memory 1152 diff --git a/test/mock/no-index-pass/src/http/get-foo/config.arc b/test/mock/no-index-pass/src/http/get-foo/config.arc index daf73a48..d9c37445 100644 --- a/test/mock/no-index-pass/src/http/get-foo/config.arc +++ b/test/mock/no-index-pass/src/http/get-foo/config.arc @@ -1,5 +1,5 @@ @aws -runtime nodejs14.x +runtime nodejs18.x # timeout 30 # concurrency 1 # memory 1152 diff --git a/test/mock/normal/app.arc b/test/mock/normal/app.arc index 9e68b58e..f29f05ab 100644 --- a/test/mock/normal/app.arc +++ b/test/mock/normal/app.arc @@ -14,12 +14,12 @@ queue-custom @http get / # runs default # Runtimes +get /nodejs20.x get /nodejs18.x -get /nodejs14.x get /node-esm +get /python3.11 get /python3.8 -get /python3.7 -get /ruby2.7 +get /ruby3.2 get /deno # Path get /get-p-c/:param/* diff --git a/test/mock/normal/src/http/get-nodejs14_x/config.arc b/test/mock/normal/src/http/get-nodejs20_x/config.arc similarity index 53% rename from test/mock/normal/src/http/get-nodejs14_x/config.arc rename to test/mock/normal/src/http/get-nodejs20_x/config.arc index c0c1cc8a..14a23854 100644 --- a/test/mock/normal/src/http/get-nodejs14_x/config.arc +++ b/test/mock/normal/src/http/get-nodejs20_x/config.arc @@ -1,5 +1,5 @@ @aws -runtime nodejs14.x -timeout 14 +runtime nodejs20.x +timeout 20 # concurrency 1 # memory 1152 diff --git a/test/mock/normal/src/http/get-nodejs14_x/index.js b/test/mock/normal/src/http/get-nodejs20_x/index.js similarity index 74% rename from test/mock/normal/src/http/get-nodejs14_x/index.js rename to test/mock/normal/src/http/get-nodejs20_x/index.js index 4209ebbd..dcd01503 100644 --- a/test/mock/normal/src/http/get-nodejs14_x/index.js +++ b/test/mock/normal/src/http/get-nodejs20_x/index.js @@ -1,6 +1,6 @@ exports.handler = async (event) => { const body = event - body.message = 'Hello from get /nodejs14.x (running nodejs14.x)' + body.message = 'Hello from get /nodejs20.x (running nodejs20.x)' return { statusCode: 200, headers: { 'content-type': 'application/json' }, diff --git a/test/mock/normal/src/http/get-python3_7/config.arc b/test/mock/normal/src/http/get-python3_11/config.arc similarity index 70% rename from test/mock/normal/src/http/get-python3_7/config.arc rename to test/mock/normal/src/http/get-python3_11/config.arc index c327c640..74555153 100644 --- a/test/mock/normal/src/http/get-python3_7/config.arc +++ b/test/mock/normal/src/http/get-python3_11/config.arc @@ -1,5 +1,5 @@ @aws -runtime python3.7 +runtime python3.11 timeout 3 # concurrency 1 # memory 1152 diff --git a/test/mock/normal/src/http/get-python3_11/index.py b/test/mock/normal/src/http/get-python3_11/index.py new file mode 100644 index 00000000..46ddd552 --- /dev/null +++ b/test/mock/normal/src/http/get-python3_11/index.py @@ -0,0 +1,12 @@ +import json + + +def handler(event, context): + body = event + body["message"] = "Hello from get /python3.11 (running python3.11)" + body["context"] = context + return { + "statusCode": 200, + "headers": {"content-type": "application/json"}, + "body": json.dumps(body), + } diff --git a/test/mock/normal/src/http/get-python3_7/index.py b/test/mock/normal/src/http/get-python3_7/index.py deleted file mode 100644 index e8c771b9..00000000 --- a/test/mock/normal/src/http/get-python3_7/index.py +++ /dev/null @@ -1,10 +0,0 @@ -import json - -def handler(event, context): - body = event - body['message'] = 'Hello from get /python3.7 (running python3.7)' - return { - 'statusCode': 200, - 'headers': { 'content-type': 'application/json' }, - 'body': json.dumps(body) - } diff --git a/test/mock/normal/src/http/get-python3_8/index.py b/test/mock/normal/src/http/get-python3_8/index.py index e3a219cd..37a333e6 100644 --- a/test/mock/normal/src/http/get-python3_8/index.py +++ b/test/mock/normal/src/http/get-python3_8/index.py @@ -1,11 +1,12 @@ import json + def handler(event, context): body = event - body['message'] = 'Hello from get /python3.8 (running python3.8)' - body['context'] = context + body["message"] = "Hello from get /python3.8 (running python3.8)" + body["context"] = context return { - 'statusCode': 200, - 'headers': { 'content-type': 'application/json' }, - 'body': json.dumps(body) + "statusCode": 200, + "headers": {"content-type": "application/json"}, + "body": json.dumps(body), } diff --git a/test/mock/normal/src/http/get-ruby2_7/config.arc b/test/mock/normal/src/http/get-ruby3_2/config.arc similarity index 56% rename from test/mock/normal/src/http/get-ruby2_7/config.arc rename to test/mock/normal/src/http/get-ruby3_2/config.arc index da2f0742..8d915619 100644 --- a/test/mock/normal/src/http/get-ruby2_7/config.arc +++ b/test/mock/normal/src/http/get-ruby3_2/config.arc @@ -1,5 +1,5 @@ @aws -runtime ruby2.7 -timeout 25 +runtime ruby3.2 +timeout 32 # concurrency 1 # memory 1152 diff --git a/test/mock/normal/src/http/get-ruby2_7/index.rb b/test/mock/normal/src/http/get-ruby3_2/index.rb similarity index 84% rename from test/mock/normal/src/http/get-ruby2_7/index.rb rename to test/mock/normal/src/http/get-ruby3_2/index.rb index 951992be..49cd2bf5 100644 --- a/test/mock/normal/src/http/get-ruby2_7/index.rb +++ b/test/mock/normal/src/http/get-ruby3_2/index.rb @@ -4,7 +4,7 @@ def handler(event:, context:) body = event - body[:message] = 'Hello from get /ruby2.7 (running ruby2.7)' + body[:message] = 'Hello from get /ruby3.2 (running ruby3.2)' body[:context] = context { statusCode: 200, diff --git a/test/mock/root-handling/greedy-get-index/src/http/get-index/config.arc b/test/mock/root-handling/greedy-get-index/src/http/get-index/config.arc index 43b9c8df..164a9299 100644 --- a/test/mock/root-handling/greedy-get-index/src/http/get-index/config.arc +++ b/test/mock/root-handling/greedy-get-index/src/http/get-index/config.arc @@ -1,5 +1,5 @@ @aws -runtime nodejs14.x +runtime nodejs18.x timeout 10 # concurrency 1 # memory 1152 diff --git a/test/mock/root-handling/param-exact/src/http/get-000param-there/config.arc b/test/mock/root-handling/param-exact/src/http/get-000param-there/config.arc index 43b9c8df..164a9299 100644 --- a/test/mock/root-handling/param-exact/src/http/get-000param-there/config.arc +++ b/test/mock/root-handling/param-exact/src/http/get-000param-there/config.arc @@ -1,5 +1,5 @@ @aws -runtime nodejs14.x +runtime nodejs18.x timeout 10 # concurrency 1 # memory 1152 diff --git a/test/mock/root-handling/root-param/src/http/get-000param/config.arc b/test/mock/root-handling/root-param/src/http/get-000param/config.arc index 43b9c8df..164a9299 100644 --- a/test/mock/root-handling/root-param/src/http/get-000param/config.arc +++ b/test/mock/root-handling/root-param/src/http/get-000param/config.arc @@ -1,5 +1,5 @@ @aws -runtime nodejs14.x +runtime nodejs18.x timeout 10 # concurrency 1 # memory 1152 diff --git a/test/unit/src/db/create-table/_get-attribute-definitions-test.js b/test/unit/src/db/create-table/_get-attribute-definitions-test.js index 85e01fce..0dc62c96 100644 --- a/test/unit/src/db/create-table/_get-attribute-definitions-test.js +++ b/test/unit/src/db/create-table/_get-attribute-definitions-test.js @@ -38,7 +38,7 @@ test('Get DynamoDB AttributeDefinitions (partition key only, manually injected)' test('Get DynamoDB AttributeDefinitions (partition key + GSI, user defined)', t => { t.plan(5) - let result = getDefns({ name: 'accounts', inventory }) + let result = getDefns({ table: { name: 'accounts' }, inventory }) t.equal(result.length, 2, 'Got back one attribute definition') t.equal(result[0].AttributeName, 'accountID', `Got back correct attribute name`) t.equal(result[0].AttributeType, 'S', `Got back correct attribute type`) @@ -60,7 +60,7 @@ test('Get DynamoDB AttributeDefinitions (partition key + multiple GSIs, user def // Note: the GSIs in this mock share key names // Thus, we demonstrate reduced properties; there aren't more attribues just because more GSIs t.plan(5) - let result = getDefns({ name: 'pets', inventory }) + let result = getDefns({ table: { name: 'pets' }, inventory }) t.equal(result.length, 2, 'Got back one attribute definition') t.equal(result[0].AttributeName, 'accountID', `Got back correct attribute name`) t.equal(result[0].AttributeType, 'S', `Got back correct attribute type`) diff --git a/test/unit/src/invoke-lambda/index-test.js b/test/unit/src/invoke-lambda/index-test.js index 642280e3..5a88fbf5 100644 --- a/test/unit/src/invoke-lambda/index-test.js +++ b/test/unit/src/invoke-lambda/index-test.js @@ -6,6 +6,7 @@ let update = require('@architect/utils').updater() let cwd = process.cwd() let mock = join(cwd, 'test', 'mock') let { invocations } = require(join(cwd, 'src', 'arc', '_runtime-api')) +let { credentials: creds } = require(join(cwd, 'test', 'utils')) let runtimes = { asap: 0, @@ -36,7 +37,7 @@ let event = { something: 'happened' } let inventory = { inv: { _project: { env: { local: { testing: null, staging: null, production: null } } }, app: 'hi' } } let ports = {} let userEnv = {} -let params = { event, inventory, update, userEnv, ports } +let params = { creds, event, inventory, update, userEnv, ports } let inv let get @@ -71,6 +72,15 @@ test('Test runtime invocations', t => { t.deepEqual(result, event, 'Default runtime received event') }) + lambda = get.http('get /nodejs20.x') + invoke({ lambda, ...params }, (err, result) => { + if (err) t.end(err) + let { options, timeout } = execPassedParams + t.equals(options.cwd, lambda.src, 'nodejs20.x passed correct path') + t.equals(timeout, 20000, 'nodejs20.x ran with correct timeout') + t.deepEqual(result, event, 'nodejs20.x received event') + }) + lambda = get.http('get /nodejs18.x') invoke({ lambda, ...params }, (err, result) => { if (err) t.end(err) @@ -80,13 +90,13 @@ test('Test runtime invocations', t => { t.deepEqual(result, event, 'nodejs18.x received event') }) - lambda = get.http('get /nodejs14.x') + lambda = get.http('get /python3.11') invoke({ lambda, ...params }, (err, result) => { if (err) t.end(err) let { options, timeout } = execPassedParams - t.equals(options.cwd, lambda.src, 'nodejs14.x passed correct path') - t.equals(timeout, 14000, 'nodejs14.x ran with correct timeout') - t.deepEqual(result, event, 'nodejs14.x received event') + t.equals(options.cwd, lambda.src, 'python3.11 passed correct path') + t.equals(timeout, 3000, 'python3.11 ran with correct timeout') + t.deepEqual(result, event, 'python3.11 received event') }) lambda = get.http('get /python3.8') @@ -98,22 +108,13 @@ test('Test runtime invocations', t => { t.deepEqual(result, event, 'python3.8 received event') }) - lambda = get.http('get /python3.7') - invoke({ lambda, ...params }, (err, result) => { - if (err) t.end(err) - let { options, timeout } = execPassedParams - t.equals(options.cwd, lambda.src, 'python3.7 passed correct path') - t.equals(timeout, 3000, 'python3.7 ran with correct timeout') - t.deepEqual(result, event, 'python3.7 received event') - }) - - lambda = get.http('get /ruby2.7') + lambda = get.http('get /ruby3.2') invoke({ lambda, ...params }, (err, result) => { if (err) t.end(err) let { options, timeout } = execPassedParams - t.equals(options.cwd, lambda.src, 'ruby2.7 passed correct path') - t.equals(timeout, 25000, 'ruby2.7 ran with correct timeout') - t.deepEqual(result, event, 'ruby2.7 received event') + t.equals(options.cwd, lambda.src, 'ruby3.2 passed correct path') + t.equals(timeout, 32000, 'ruby3.2 ran with correct timeout') + t.deepEqual(result, event, 'ruby3.2 received event') }) lambda = get.http('get /deno') diff --git a/test/unit/src/sandbox-test.js b/test/unit/src/sandbox-test.js index ada73e11..0e2c2066 100644 --- a/test/unit/src/sandbox-test.js +++ b/test/unit/src/sandbox-test.js @@ -83,11 +83,12 @@ test('Sandbox uses continuation passing', t => { ]) }) -// Standard env vars that may be populated during a banner / AWS init +// Nothing should be mutating these, but reset them jic! let envVars = [ 'ARC_APP_NAME', 'ARC_AWS_CREDS', 'ARC_ENV', + 'ARC_SANDBOX', 'AWS_ACCESS_KEY_ID', 'AWS_PROFILE', 'AWS_REGION', @@ -118,6 +119,7 @@ test('Sandbox only minimally mutates env vars', async t => { // Architect 6+ (staging/prod) before = copy(process.env) process.env.ARC_ENV = 'staging' + process.env.ARC_SANDBOX = '{}' // Force aws-lite to disable keepalive await sandbox.start({ cwd: join(mock, 'normal'), port, quiet }) after = copy(process.env) envVars.forEach(v => delete after[v]) diff --git a/test/unit/src/sandbox/check-runtimes/version-check-test.js b/test/unit/src/sandbox/check-runtimes/version-check-test.js index f2953436..1354b429 100644 --- a/test/unit/src/sandbox/check-runtimes/version-check-test.js +++ b/test/unit/src/sandbox/check-runtimes/version-check-test.js @@ -17,13 +17,13 @@ test('Project global runtime config', async t => { rawArc = basic inventory = await _inventory({ rawArc }) - localRuntimes = { node: '16.0.0' } + localRuntimes = { node: '20.0.0' } result = versionCheck({ cwd, inventory, localRuntimes }) t.notOk(result, 'Control: no runtime configuration did not return any issues') rawArc = basic + '\n@aws\nruntime node' inventory = await _inventory({ rawArc }) - localRuntimes = { node: '16.0.0' } + localRuntimes = { node: '20.0.0' } result = versionCheck({ cwd, inventory, localRuntimes }) t.notOk(result, 'Control: compatible runtime configuration did not return any issues') @@ -86,7 +86,7 @@ test('Project global runtime config', async t => { t.ok(result[1].includes('aliased to ruby'), 'Reported issue with alias') // Minor - rawArc = basic + '\n@aws\nruntime ruby2.7' + rawArc = basic + '\n@aws\nruntime ruby3.2' inventory = await _inventory({ rawArc }) localRuntimes = { ruby: '2.6.0' } result = versionCheck({ cwd, inventory, localRuntimes }) @@ -94,7 +94,7 @@ test('Project global runtime config', async t => { t.ok(result[1].includes('Project global runtime'), 'Reported issue with project global runtime') // Major - rawArc = basic + '\n@aws\nruntime ruby2.7' + rawArc = basic + '\n@aws\nruntime ruby3.2' inventory = await _inventory({ rawArc }) localRuntimes = { ruby: '1.7.0' } result = versionCheck({ cwd, inventory, localRuntimes }) @@ -109,20 +109,20 @@ test('Per-Lambda runtime config', async t => { rawArc = basic inventory = await _inventory({ rawArc }) - localRuntimes = { node: '16.0.0' } + localRuntimes = { node: '20.0.0' } result = versionCheck({ cwd, inventory, localRuntimes }) t.notOk(result, 'Control: no runtime configuration did not return any issues') inventory = await _inventory({ rawArc }) - inventory.inv.http[0].config.runtime = 'nodejs14.x' - localRuntimes = { node: '16.0.0' } + inventory.inv.http[0].config.runtime = 'nodejs18.x' + localRuntimes = { node: '20.0.0' } result = versionCheck({ cwd, inventory, localRuntimes }) t.notOk(result, 'Control: compatible runtime configuration did not return any issues') // Minor inventory = await _inventory({ rawArc }) - inventory.inv.http[0].config.runtime = 'nodejs14.x' - localRuntimes = { node: '14.1.0' } + inventory.inv.http[0].config.runtime = 'nodejs18.x' + localRuntimes = { node: '18.1.0' } result = versionCheck({ cwd, inventory, localRuntimes }) t.notOk(result, 'Compatible runtime configuration did not return any issues') @@ -152,17 +152,17 @@ test('Per-Lambda runtime config', async t => { // Minor inventory = await _inventory({ rawArc }) - inventory.inv.http[0].config.runtime = 'ruby2.7' + inventory.inv.http[0].config.runtime = 'ruby3.2' localRuntimes = { ruby: '2.6.0' } result = versionCheck({ cwd, inventory, localRuntimes }) console.log(result[1]) - t.ok(result[1].includes('ruby2.7'), 'Reported issue with Lambda runtime') + t.ok(result[1].includes('ruby3.2'), 'Reported issue with Lambda runtime') // Major inventory = await _inventory({ rawArc }) - inventory.inv.http[0].config.runtime = 'ruby2.7' + inventory.inv.http[0].config.runtime = 'ruby3.2' localRuntimes = { ruby: '1.7.0' } result = versionCheck({ cwd, inventory, localRuntimes }) console.log(result[1]) - t.ok(result[1].includes('ruby2.7'), 'Reported issue with Lambda runtime') + t.ok(result[1].includes('ruby3.2'), 'Reported issue with Lambda runtime') }) diff --git a/test/utils/_lib.js b/test/utils/_lib.js index 51dbfbd6..4a021279 100644 --- a/test/utils/_lib.js +++ b/test/utils/_lib.js @@ -9,8 +9,8 @@ let copy = thing => JSON.parse(JSON.stringify(thing)) // Dummy AWS creds let credentials = { - accessKeyId: 'xxx', - secretAccessKey: 'xxx', + accessKeyId: 'arc_dummy_access_key', + secretAccessKey: 'arc_dummy_secret_key', } let data = { hi: 'there' }