Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws-lite #72

Merged
merged 16 commits into from
Feb 2, 2024
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [ 14.x, 16.x, 18.x, 20.x ]
node-version: [ 16.x, 18.x, 20.x ]
os: [ windows-latest, ubuntu-latest, macOS-latest ]

# Go
Expand Down Expand Up @@ -49,7 +49,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"
Expand Down
12 changes: 12 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

---

## [4.0.0] 2024-01-08

### Changed

- Transitioned from `aws-sdk` to [`aws-lite`](https://aws-lite.org)
- Breaking change: `arm64` is now the default Lambda architecture
- 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

---

## [3.6.5] 2023-12-07

### Changed
Expand Down
19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@architect/inventory",
"version": "3.6.5",
"version": "4.0.0-RC.4",
"description": "Architect project resource enumeration utility",
"main": "src/index.js",
"scripts": {
Expand All @@ -21,22 +21,23 @@
},
"license": "Apache-2.0",
"dependencies": {
"@architect/asap": "~6.0.4",
"@architect/asap": "~7.0.0-RC.2",
"@architect/parser": "~6.0.3",
"@architect/utils": "~3.1.9",
"lambda-runtimes": "~1.1.6"
"@architect/utils": "~4.0.0-RC.4",
"@aws-lite/client": "^0.15.1",
"@aws-lite/ssm": "^0.2.2",
"lambda-runtimes": "~2.0.0"
},
"devDependencies": {
"@architect/eslint-config": "~2.1.2",
"aws-sdk": "^2.1363.0",
"aws-sdk-mock": "~5.8.0",
"cross-env": "~7.0.3",
"dotenv": "~16.3.1",
"eslint": "~8.55.0",
"dotenv": "~16.4.1",
"eslint": "~8.56.0",
"mock-tmp": "~0.0.2",
"nyc": "~15.1.0",
"proxyquire": "~2.1.3",
"tap-arc": "^1.2.2",
"tape": "^5.7.2"
"tape": "^5.7.4"
},
"eslintConfig": {
"extends": "@architect/eslint-config"
Expand Down
4 changes: 2 additions & 2 deletions src/defaults/function-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ module.exports = function createDefaultFunctionConfig () {
return {
timeout: 5,
memory: 1152,
runtime: 'nodejs16.x',
architecture: 'x86_64', // TODO [BREAKING]: default to 'arm64'
runtime: 'nodejs20.x',
architecture: 'arm64',
handler: 'index.handler',
state: 'n/a',
concurrency: 'unthrottled',
Expand Down
77 changes: 24 additions & 53 deletions src/env/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,68 +8,40 @@ module.exports = function env (params, inventory, callback) {
return callback()
}

/* istanbul ignore next */
try {
// eslint-disable-next-line
try { require('aws-sdk/lib/maintenance_mode_message').suppress = true }
catch { /* Noop */ }
// eslint-disable-next-line
var aws = require('aws-sdk')
}
catch (err) {
let msg = `'aws-sdk' not found, please install locally or globally (see also readme#aws-sdk-caveat)`
return callback(Error(msg))
}
let aws
let name = inventory.app
let { region } = inventory.aws
let ssm = new aws.SSM({ region })
let { profile, region } = inventory.aws
let result = []
// eslint-disable-next-line
let awsLite = require('@aws-lite/client')
/* istanbul ignore next */
awsLite({ profile, region }).then(_aws => {
aws = _aws

function getSomeEnvVars (name, NextToken, callback) {
// Base query to ssm
let query = {
// Perform the query
let params = {
Path: `/${name}`,
Recursive: true,
MaxResults: 10,
WithDecryption: true
WithDecryption: true,
paginate: true
}

// Check if we're paginating
/* istanbul ignore if */
if (NextToken) query.NextToken = NextToken

// Perform the query
ssm.getParametersByPath(query, function _query (err, data) {
if (err) callback(err)
else {
// Tidy up the response
result = result.concat(data.Parameters.map(function (param) {
let bits = param.Name.split('/')
return {
app: name, // jic
env: bits[2],
name: bits[3],
value: param.Value,
}
}))
// Check for more data and, if so, recurse
/* istanbul ignore if: Sadly no way to easily mock this for testing */
if (data.NextToken) {
getSomeEnvVars(name, data.NextToken, callback)
aws.ssm.GetParametersByPath(params).then(data => {
// Tidy up the response
result = result.concat(data.Parameters.map(param => {
let bits = param.Name.split('/')
return {
app: name, // jic
env: bits[2],
name: bits[3],
value: param.Value,
}
else callback(null, result)
}
})
}
}))

getSomeEnvVars(name, false, function done (err, result) {
if (err) callback(err)
else {
let testing = null
let staging = null
let production = null
if (result.length) {
// TODO refactor into a reducer?
result.forEach(({ env, name: k, value: v }) => {
if (env === 'testing') testing = Object.assign({}, testing, { [k]: v })
if (env === 'staging') staging = Object.assign({}, staging, { [k]: v })
Expand All @@ -85,10 +57,9 @@ module.exports = function env (params, inventory, callback) {
errors,
})
if (errors.length) {
callback(Error(errors[0]))
return
return callback(Error(errors[0]))
}
callback()
}
})
}).catch(err => callback(err))
}).catch(err => callback(err))
}
10 changes: 5 additions & 5 deletions test/integration/function-config-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ test('[No global runtime] Inventory and compare functions with / without functio
t.ok(get, 'Inventory returned getter')
let def = inv._project.defaultFunctionConfig
let custom = {
runtime: 'nodejs16.x',
runtime: 'nodejs20.x',
runtimeAlias: 'node',
architecture: 'arm64',
architecture: 'x86_64',
timeout: 10,
memory: 128,
storage: 1337,
Expand Down Expand Up @@ -71,9 +71,9 @@ test('[Global runtime alias] Inventory and compare functions with / without func
t.ok(get, 'Inventory returned getter')
let def = inv._project.defaultFunctionConfig
let custom = {
runtime: 'nodejs14.x',
runtime: 'nodejs18.x',
runtimeAlias: undefined,
architecture: 'arm64',
architecture: 'x86_64',
timeout: 10,
memory: 128,
storage: 1337,
Expand All @@ -97,7 +97,7 @@ test('[Global runtime alias] Inventory and compare functions with / without func
Object.keys(custom).forEach(p => {
let setting
if (p === 'views') setting = str(true)
else if (p === 'runtime') setting = str('python3.9')
else if (p === 'runtime') setting = str('python3.12')
else if (p === 'runtimeAlias') setting = str('py')
else setting = str(def[p])
t.equal(str(config[p]), setting, `get /default has correct default ${p} setting: ${str(config[p])}`)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Non-defaults all around
@aws
runtime nodejs14.x
runtime nodejs18.x
timeout 10
memory 128
storage 1337
layers
arn:a:b:us-west-1:c:d:e:f
policies
arn:b:c:us-west-1:d:e:f:g
architecture arm64
architecture x86_64

@arc
shared false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ layers
arn:a:b:us-west-1:c:d:e:f
policies
arn:b:c:us-west-1:d:e:f:g
architecture arm64
architecture x86_64

@arc
shared false
Expand Down
2 changes: 1 addition & 1 deletion test/unit/src/config/_upsert-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ layers
policies
policy-1
policy-2
architecture arm64
architecture x86_64
`
let mock = parse(rawConfigMock)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ test('Friendly runtime names (aka aliases)', t => {
let config

config = getRuntimes({ config: c('Node.js'), inventory })
t.match(config.runtime, /nodejs1[02468]\.x/, `Alias mapped to valid AWS Node.js string: ${config.runtime}`)
t.match(config.runtime, /nodejs2[02468]\.x/, `Alias mapped to valid AWS Node.js string: ${config.runtime}`)
t.equal(config.runtimeAlias, 'node.js', `Alias returned lowcase as runtimeAlias: ${config.runtimeAlias}`)

config = getRuntimes({ config: c('Python'), inventory })
t.match(config.runtime, /python3\.\d/, `Alias mapped to valid AWS Python string: ${config.runtime}`)
t.equal(config.runtimeAlias, 'python', `Alias returned lowcase as runtimeAlias: ${config.runtimeAlias}`)

config = getRuntimes({ config: c('ruby'), inventory })
t.match(config.runtime, /ruby2\.\d/, `Alias mapped to valid AWS Ruby string: ${config.runtime}`)
t.match(config.runtime, /ruby3\.\d/, `Alias mapped to valid AWS Ruby string: ${config.runtime}`)
t.equal(config.runtimeAlias, 'ruby', `Alias returned lowcase as runtimeAlias: ${config.runtimeAlias}`)

config = getRuntimes({ config: c('java'), inventory })
Expand Down
4 changes: 2 additions & 2 deletions test/unit/src/config/pragmas/populate-lambda/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ custom setting
modified = {
timeout: 10,
memory: 128,
runtime: `nodejs16.x`,
runtime: 'nodejs20.x',
handler: 'index.handler',
custom: 'setting',
}
Expand All @@ -325,7 +325,7 @@ custom setting
modified = {
timeout: 10,
memory: 128,
runtime: `nodejs16.x`,
runtime: 'nodejs20.x',
handler: 'lambda.handler',
custom: 'setting',
}
Expand Down
2 changes: 1 addition & 1 deletion test/unit/src/config/project/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ test('Project plugins', t => {

// Env + custom runtime plugins
let env = { henlo: 'friend' }
let runtime = { name: 'typescript', type: 'transpiled', build: 'dist', baseRuntime: 'nodejs14.x' }
let runtime = { name: 'typescript', type: 'transpiled', build: 'dist', baseRuntime: 'nodejs20.x' }
let plugins = { _methods: { set: {
env: [ () => (env) ],
runtimes: [ () => (runtime) ],
Expand Down
8 changes: 4 additions & 4 deletions test/unit/src/config/project/plugins/runtimes-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ test('Transpiled runtime setters', t => {
let inventory, plugin, plugins, runtime
let type = 'transpiled'
let build = '.build' // Just make sure it's different from the default 'build'
let baseRuntime = 'nodejs14.x'
let baseRuntime = 'nodejs20.x'
let errors = []

// Transpiled with default build dir
Expand Down Expand Up @@ -166,7 +166,7 @@ test('Runtime setter validation', t => {
t.plan(16)
let errors, inventory, plugin, runtime
let type = 'transpiled'
let baseRuntime = 'nodejs14.x'
let baseRuntime = 'nodejs20.x'

// No name
runtime = { type }
Expand Down Expand Up @@ -205,13 +205,13 @@ test('Runtime setter validation', t => {
t.match(errors[0], /Runtime plugin must provide a valid type/, 'Returned correct type error')

// Name cannot conflict with an existing runtime
runtime = { name: 'nodejs14.x', type }
runtime = { name: 'nodejs20.x', type }
plugin = () => runtime
inventory = newInv([ plugin ])
errors = []
setRuntimesPlugins({ inventory, errors }, emptyProj)
t.equal(errors.length, 1, 'Returned an error')
t.match(errors[0], /Runtime name 'nodejs14\.x' is reserved/, 'Returned correct name error')
t.match(errors[0], /Runtime name 'nodejs20\.x' is reserved/, 'Returned correct name error')

// Name cannot conflict with an existing custom runtime
runtime = { name, type, baseRuntime }
Expand Down
23 changes: 14 additions & 9 deletions test/unit/src/env/index-test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
let { join } = require('path')
let test = require('tape')
let proxyquire = require('proxyquire')

async function awsLite () {
return { ssm: {
GetParametersByPath: async () => {
if (response instanceof Error) throw response
return response
}
} }
}

let sut = join(process.cwd(), 'src', 'env')
let getEnv = require(sut)
let awsMock = require('aws-sdk-mock')
let aws = require('aws-sdk')
awsMock.setSDKInstance(aws)
let getEnv = proxyquire(sut, {
'@aws-lite/client': awsLite
})

let app = 'an-app'
let nulls = {
Expand Down Expand Up @@ -41,10 +51,6 @@ let reset = () => {
test('Set up env', t => {
t.plan(1)
t.ok(getEnv, 'Env var getter is present')
awsMock.mock('SSM', 'getParametersByPath', function (p, callback) {
if (response instanceof Error) callback(response)
else callback(null, response)
})
})

test('Do nothing', t => {
Expand Down Expand Up @@ -261,6 +267,5 @@ test('Error handling', t => {

test('Teardown', t => {
t.plan(1)
awsMock.restore()
t.pass('All done')
})
2 changes: 1 addition & 1 deletion test/unit/src/validate/config-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let reset = () => {
}

let name = 'an-event'
let okRuntime = 'nodejs14.x'
let okRuntime = 'nodejs20.x'
let okMemory = 1000
let okTimeout = 30
let okStorage = 1024
Expand Down
2 changes: 1 addition & 1 deletion test/unit/src/validate/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ test('Configuration errors', t => {
test('Table validation errors', t => {
t.plan(1)
let tables = [ { name: 'table' } ]
let streams = [ { name: 'foo', table: 'foo', config: { runtime: 'nodejs14.x', ...config } } ]
let streams = [ { name: 'foo', table: 'foo', config: { runtime: 'nodejs20.x', ...config } } ]
let inventory = { ...defaults, tables, 'tables-streams': streams }
let err = finalValidation(params, inventory)
if (!err) t.fail('Expected an error')
Expand Down
Loading