@architect/inventory 2.1.0 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +41 -2
- package/package.json +12 -4
- package/readme.md +1 -1
- package/src/config/_upsert.js +0 -4
- package/src/config/pragmas/populate-lambda/_scheduled.js +12 -4
- package/src/config/pragmas/populate-lambda/get-runtime.js +27 -0
- package/src/config/pragmas/populate-lambda/index.js +4 -0
- package/src/config/pragmas/validate/_scheduled.js +1 -6
- package/src/lib/is.js +2 -1
- package/src/validate/config.js +64 -0
- package/src/validate/index.js +3 -4
- package/src/validate/layers.js +65 -33
- package/src/lib/runtimes.js +0 -84
- package/src/validate/arn.js +0 -24
- package/src/validate/runtimes.js +0 -28
package/changelog.md
CHANGED
|
@@ -2,12 +2,51 @@
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
+
## [2.1.3] 2021-11-04
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Hardened runtime validation by ensuring non-string values will fail gracefully
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## [2.1.2] 2021-10-28
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Added memory / timeout configuration validation
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Improved layer validation error formatting
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## [2.1.1] 2021-10-13
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Added `config.runtimeAlias` property to Lambdas whose `config.runtime` is interpolated by way of latest-runtime aliasing (e.g. `node` or `py`)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- Internal change: implement [Lambda runtimes module](https://www.npmjs.com/package/lambda-runtimes) instead of maintaining valid runtime list in Inventory
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- Fixed `@scheduled` parsing in `app.json` + `package.json` > `arc.scheduled`
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
5
44
|
## [2.1.0] 2021-10-11
|
|
6
45
|
|
|
7
46
|
### Added
|
|
8
47
|
|
|
9
|
-
- Added latest-runtime version
|
|
10
|
-
- Example:
|
|
48
|
+
- Added latest-runtime version aliasing
|
|
49
|
+
- Example: you want your app to always run the latest Lambda version of Python (instead of specifying `python3.9`(and changing it every time a new version of Python is released); now you can specify `python` or `py`
|
|
11
50
|
- Valid shortcuts: Node.js: `node`, `nodejs`, `node.js`; Python: `python`, `py`; Ruby: `ruby`, `rb`; Java: `java`; Go: `go`, `golang`; .NET: `dotnet`, `.net`; and custom runtimes: `custom`
|
|
12
51
|
- Added runtime validation
|
|
13
52
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@architect/inventory",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "Architect project resource enumeration utility",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,14 +22,15 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@architect/asap": "~4.1.0",
|
|
24
24
|
"@architect/parser": "~5.0.2",
|
|
25
|
-
"@architect/utils": "~3.0.
|
|
25
|
+
"@architect/utils": "~3.0.4",
|
|
26
|
+
"lambda-runtimes": "~1.0.1"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"@architect/eslint-config": "~2.0.1",
|
|
29
30
|
"aws-sdk": "2.880.0",
|
|
30
|
-
"aws-sdk-mock": "5.4.0",
|
|
31
|
+
"aws-sdk-mock": "~5.4.0",
|
|
31
32
|
"cross-env": "~7.0.3",
|
|
32
|
-
"eslint": "~8.0.
|
|
33
|
+
"eslint": "~8.0.1",
|
|
33
34
|
"mock-fs": "~5.1.1",
|
|
34
35
|
"mock-require": "~3.0.3",
|
|
35
36
|
"nyc": "~15.1.0",
|
|
@@ -38,5 +39,12 @@
|
|
|
38
39
|
},
|
|
39
40
|
"eslintConfig": {
|
|
40
41
|
"extends": "@architect/eslint-config"
|
|
42
|
+
},
|
|
43
|
+
"nyc": {
|
|
44
|
+
"check-coverage": true,
|
|
45
|
+
"branches": 100,
|
|
46
|
+
"lines": 100,
|
|
47
|
+
"functions": 100,
|
|
48
|
+
"statements": 100
|
|
41
49
|
}
|
|
42
50
|
}
|
package/readme.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[<img src="https://
|
|
1
|
+
[<img src="https://assets.arc.codes/architect-logo-500b@2x.png" width=500>](https://www.npmjs.com/package/@architect/inventory)
|
|
2
2
|
|
|
3
3
|
## [`@architect/inventory`](https://www.npmjs.com/package/@architect/inventory)
|
|
4
4
|
|
package/src/config/_upsert.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
let is = require('../lib/is')
|
|
2
|
-
let runtimes = require('../lib/runtimes')
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Overlay / append properties onto an existing config object
|
|
@@ -60,9 +59,6 @@ module.exports = function upsertProps (config, newConfig) {
|
|
|
60
59
|
else if (name === 'policies' && !!(value)) {
|
|
61
60
|
policies = policies.concat(value)
|
|
62
61
|
}
|
|
63
|
-
else if (name === 'runtime' && !!(value)) {
|
|
64
|
-
props.runtime = runtimes(value[0])
|
|
65
|
-
}
|
|
66
62
|
else {
|
|
67
63
|
props[name] = value[0]
|
|
68
64
|
}
|
|
@@ -33,7 +33,7 @@ let get = {
|
|
|
33
33
|
module.exports = function populateScheduled ({ item, dir, cwd, errors }) {
|
|
34
34
|
let rate = null
|
|
35
35
|
let cron = null
|
|
36
|
-
if (is.array(item)
|
|
36
|
+
if (is.array(item)) {
|
|
37
37
|
let name = item[0]
|
|
38
38
|
|
|
39
39
|
// Hacky but it works
|
|
@@ -52,9 +52,17 @@ module.exports = function populateScheduled ({ item, dir, cwd, errors }) {
|
|
|
52
52
|
else if (is.object(item)) {
|
|
53
53
|
let name = Object.keys(item)[0]
|
|
54
54
|
|
|
55
|
-
// Handle rate + cron
|
|
56
|
-
if (item[name].rate)
|
|
57
|
-
|
|
55
|
+
// Handle rate + cron props
|
|
56
|
+
if (item[name].rate) {
|
|
57
|
+
let itemRate = item[name].rate
|
|
58
|
+
let exp = is.array(itemRate) ? itemRate.join(' ') : itemRate
|
|
59
|
+
rate = get.rate(exp)
|
|
60
|
+
}
|
|
61
|
+
if (item[name].cron) {
|
|
62
|
+
let itemCron = item[name].cron
|
|
63
|
+
let exp = is.array(itemCron) ? itemCron.join(' ') : itemCron
|
|
64
|
+
cron = get.cron(exp)
|
|
65
|
+
}
|
|
58
66
|
|
|
59
67
|
let src = item[name].src
|
|
60
68
|
? join(cwd, item[name].src)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
let is = require('../../../lib/is')
|
|
2
|
+
let { aliases, runtimes, runtimeList } = require('lambda-runtimes')
|
|
3
|
+
|
|
4
|
+
// Runtime interpolater
|
|
5
|
+
module.exports = function getRuntime (config) {
|
|
6
|
+
let { runtime } = config
|
|
7
|
+
|
|
8
|
+
if (runtimeList.includes(runtime) || runtime === 'deno') {
|
|
9
|
+
return config
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (typeof runtime === 'string') {
|
|
13
|
+
runtime = runtime.toLowerCase()
|
|
14
|
+
|
|
15
|
+
// Runtime is not actually an AWS value, but a shorthand/aliased name
|
|
16
|
+
if (aliases[runtime]) {
|
|
17
|
+
let aliased = aliases[runtime]
|
|
18
|
+
config.runtime = runtimes[aliased][0]
|
|
19
|
+
config.runtimeAlias = runtime
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else if (is.defined(runtime)) {
|
|
23
|
+
// Someone did something funky like specify a number or bool, so coerce and let it fail validation
|
|
24
|
+
config.runtime = `${config.runtime}`
|
|
25
|
+
}
|
|
26
|
+
return config
|
|
27
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
let read = require('../../../read')
|
|
2
|
+
let getRuntime = require('./get-runtime')
|
|
2
3
|
let getHandler = require('./get-handler')
|
|
3
4
|
let upsert = require('../../_upsert')
|
|
4
5
|
let is = require('../../../lib/is')
|
|
@@ -58,6 +59,9 @@ function populateLambda (type, pragma, inventory, errors) {
|
|
|
58
59
|
config = upsert(config, arcConfig.arc)
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
// Interpolate runtimes
|
|
63
|
+
config = getRuntime(config)
|
|
64
|
+
|
|
61
65
|
// Tidy up any irrelevant params
|
|
62
66
|
if (type !== 'http') {
|
|
63
67
|
delete config.apigateway
|
|
@@ -53,7 +53,6 @@ function validateCron (schedule, errors) {
|
|
|
53
53
|
if (!year.toString().match(minHrYr)) expErr('year', year)
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
57
56
|
let singular = [ 'minute', 'hour', 'day' ]
|
|
58
57
|
let plural = [ 'minutes', 'hours', 'days' ]
|
|
59
58
|
function validateRate (schedule, errors) {
|
|
@@ -69,11 +68,7 @@ function validateRate (schedule, errors) {
|
|
|
69
68
|
|
|
70
69
|
// Value must be a >0 number
|
|
71
70
|
if (!is.number(value) || !(value > 0)) {
|
|
72
|
-
expErr('rate value must be a number greater than 0', value)
|
|
73
|
-
}
|
|
74
|
-
// Value must be a whole number
|
|
75
|
-
else if (!value.toString().match(/^\d+$/)) {
|
|
76
|
-
expErr('rate value must be a whole number', value)
|
|
71
|
+
expErr('rate value must be a whole number greater than 0', value)
|
|
77
72
|
}
|
|
78
73
|
// Interval must be a string
|
|
79
74
|
if (!is.string(interval)) {
|
package/src/lib/is.js
CHANGED
|
@@ -4,9 +4,10 @@ module.exports = {
|
|
|
4
4
|
// Types
|
|
5
5
|
array: item => Array.isArray(item),
|
|
6
6
|
bool: item => typeof item === 'boolean',
|
|
7
|
-
number: item =>
|
|
7
|
+
number: item => Number.isInteger(item),
|
|
8
8
|
object: item => typeof item === 'object' && !Array.isArray(item),
|
|
9
9
|
string: item => typeof item === 'string',
|
|
10
|
+
defined: item => typeof item !== 'undefined' && item !== null,
|
|
10
11
|
// Filesystem
|
|
11
12
|
exists: path => existsSync(path),
|
|
12
13
|
folder: path => existsSync(path) && lstatSync(path).isDirectory(),
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
let is = require('../lib/is')
|
|
2
|
+
let { lambdas } = require('../lib/pragmas')
|
|
3
|
+
let { aliases, runtimeList } = require('lambda-runtimes')
|
|
4
|
+
let allRuntimes = runtimeList.concat([ 'deno' ])
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration validator
|
|
8
|
+
*/
|
|
9
|
+
module.exports = function configValidator (params, inventory, errors) {
|
|
10
|
+
let { runtime: globalRuntime, memory: globalMemory, timeout: globalTimeout } = inventory.aws
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Global config
|
|
14
|
+
*/
|
|
15
|
+
// Memory
|
|
16
|
+
if (is.defined(globalMemory) && invalidMemory(globalMemory)) {
|
|
17
|
+
errors.push(invalidMemoryMsg(`${globalMemory} MB (@aws)`))
|
|
18
|
+
}
|
|
19
|
+
// Runtime
|
|
20
|
+
if ((globalRuntime && !is.string(globalRuntime)) ||
|
|
21
|
+
(globalRuntime && !allRuntimes.includes(globalRuntime) &&
|
|
22
|
+
!aliases[globalRuntime] && !aliases[globalRuntime.toLowerCase()])) {
|
|
23
|
+
errors.push(`Invalid project-level runtime: ${globalRuntime}`)
|
|
24
|
+
}
|
|
25
|
+
// Timeout
|
|
26
|
+
if (is.defined(globalTimeout) && invalidTimeout(globalTimeout)) {
|
|
27
|
+
errors.push(invalidTimeoutMsg(`${globalTimeout} seconds (@aws)`))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Lambda config
|
|
32
|
+
*/
|
|
33
|
+
lambdas.forEach(p => {
|
|
34
|
+
let pragma = inventory[p]
|
|
35
|
+
if (pragma) pragma.forEach(({ name, config }) => {
|
|
36
|
+
let { memory, runtime, timeout } = config
|
|
37
|
+
|
|
38
|
+
// Memory
|
|
39
|
+
if (invalidMemory(memory) && memory !== globalMemory) {
|
|
40
|
+
errors.push(invalidMemoryMsg(`${memory} MB (@${p} ${name})`))
|
|
41
|
+
}
|
|
42
|
+
// Runtime
|
|
43
|
+
if (!allRuntimes.includes(runtime) && runtime !== globalRuntime) {
|
|
44
|
+
errors.push(`Invalid runtime: ${runtime} (@${p} ${name})`)
|
|
45
|
+
}
|
|
46
|
+
// Timeout
|
|
47
|
+
if (invalidTimeout(timeout) && timeout !== globalTimeout) {
|
|
48
|
+
errors.push(invalidTimeoutMsg(`${timeout} seconds (@${p} ${name})`))
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Memory
|
|
55
|
+
let minMemory = 128
|
|
56
|
+
let maxMemory = 10240
|
|
57
|
+
let invalidMemory = memory => !is.number(memory) || (memory < minMemory) || (memory > maxMemory)
|
|
58
|
+
let invalidMemoryMsg = info => `Invalid Lambda memory setting: ${info}, memory must be between ${minMemory} - ${maxMemory} MB`
|
|
59
|
+
|
|
60
|
+
// Timeout
|
|
61
|
+
let minTimeout = 1
|
|
62
|
+
let maxTimeout = 1 * 60 * 15 // 15 mins
|
|
63
|
+
let invalidTimeout = timeout => !is.number(timeout) || (timeout < minTimeout) || (timeout > maxTimeout)
|
|
64
|
+
let invalidTimeoutMsg = info => `Invalid Lambda timeout setting: ${info}, timeout must be between ${minTimeout} - ${maxTimeout} seconds`
|
package/src/validate/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
let
|
|
1
|
+
let config = require('./config')
|
|
2
2
|
let layers = require('./layers')
|
|
3
3
|
let tablesChildren = require('./tables-children')
|
|
4
4
|
let errorFmt = require('../lib/error-fmt')
|
|
@@ -12,9 +12,8 @@ module.exports = function finalValidation (params, inventory) {
|
|
|
12
12
|
/**
|
|
13
13
|
* Deal with vendor configuration errors
|
|
14
14
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
runtimes(params, inventory, errors)
|
|
15
|
+
// Analyze function configuration
|
|
16
|
+
config(params, inventory, errors)
|
|
18
17
|
|
|
19
18
|
// Ensure layer configuration will work, AWS blows up with awful errors on this
|
|
20
19
|
layers(params, inventory, errors)
|
package/src/validate/layers.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
let { sep } = require('path')
|
|
2
2
|
let { lambdas } = require('../lib/pragmas')
|
|
3
|
-
let
|
|
3
|
+
let is = require('../lib/is')
|
|
4
|
+
let plural = arr => arr.length > 1 ? 's' : ''
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Layer validator
|
|
7
8
|
*/
|
|
8
9
|
module.exports = function layerValidator (params, inventory, errors) {
|
|
9
|
-
let {
|
|
10
|
+
let { _project } = inventory
|
|
11
|
+
let { region, layers: globalLayers } = inventory.aws
|
|
10
12
|
let { cwd, validateLayers = true } = params
|
|
11
13
|
|
|
12
14
|
// Shouldn't be possible because we backfill region, but jic
|
|
@@ -15,39 +17,69 @@ module.exports = function layerValidator (params, inventory, errors) {
|
|
|
15
17
|
// Allow for manual opt-out of layer validation
|
|
16
18
|
if (!validateLayers) return
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
})
|
|
34
|
-
}
|
|
20
|
+
/**
|
|
21
|
+
* Global config
|
|
22
|
+
*/
|
|
23
|
+
let location = _project?.manifest?.replace(cwd, '')
|
|
24
|
+
validateLayer({ layers: globalLayers, region, location, errors })
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Lambda config
|
|
28
|
+
*/
|
|
29
|
+
lambdas.forEach(p => {
|
|
30
|
+
let pragma = inventory[p]
|
|
31
|
+
if (pragma) pragma.forEach(({ config, configFile }) => {
|
|
32
|
+
let location = configFile?.replace(cwd, '')
|
|
33
|
+
validateLayer({ layers: config.layers, region, location, errors })
|
|
34
|
+
})
|
|
35
35
|
})
|
|
36
|
+
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
// CloudFormation fails without a helpful error if any layers aren't in the same region as the app because CloudFormation
|
|
47
|
-
for (let arn of layers) {
|
|
48
|
-
let arnError = validateARN({ arn, region, loc })
|
|
49
|
-
if (arnError) errors.push(arnError)
|
|
50
|
-
}
|
|
38
|
+
function validateLayer ({ layers, region, location, errors }) {
|
|
39
|
+
let loc = location && location.startsWith(sep) ? location.substr(1) : location
|
|
40
|
+
let config = loc ? ` (${loc})` : ''
|
|
41
|
+
if (!layers || !layers.length) return
|
|
42
|
+
else {
|
|
43
|
+
if (layers.length > 5) {
|
|
44
|
+
let list = `${layers.map(l => ` - ${l}`).join('\n')}`
|
|
45
|
+
errors.push(`Lambdas can only be configured with up to 5 layers, got ${layers.length} layers${config}:\n${list}`)
|
|
51
46
|
}
|
|
47
|
+
// CloudFormation fails without a helpful error if any layers aren't in the same region as the app because CloudFormation
|
|
48
|
+
let arnErrors = validateARN({ layers, region, config })
|
|
49
|
+
if (arnErrors) errors.push(arnErrors)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Validates Lambda layer / policy ARNs, prob can't be used for other kinds of ARN
|
|
54
|
+
function validateARN ({ layers, region, config }) {
|
|
55
|
+
let invalidArns = []
|
|
56
|
+
let badRegions = []
|
|
57
|
+
layers.forEach(arn => {
|
|
58
|
+
let parts = is.string(arn) && arn.split(':')
|
|
59
|
+
// Invalid
|
|
60
|
+
if (!is.string(arn) ||
|
|
61
|
+
!arn.startsWith('arn:') ||
|
|
62
|
+
parts.length !== 8) {
|
|
63
|
+
return invalidArns.push(` - ${arn}`)
|
|
64
|
+
}
|
|
65
|
+
// Bad region
|
|
66
|
+
let layerRegion = parts[3]
|
|
67
|
+
if (region !== layerRegion) {
|
|
68
|
+
badRegions.push(
|
|
69
|
+
` - Layer ARN: ${arn}\n` +
|
|
70
|
+
` - Layer region: ${layerRegion}`
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
let err = ''
|
|
75
|
+
if (invalidArns.length) {
|
|
76
|
+
err += `Invalid ARN${plural(invalidArns)}${config}:\n` +
|
|
77
|
+
invalidArns.join('\n')
|
|
78
|
+
}
|
|
79
|
+
if (badRegions.length) {
|
|
80
|
+
err += `Layer${plural(badRegions)} ` +
|
|
81
|
+
`not in app's region of ${region}${config}:\n` +
|
|
82
|
+
badRegions.join('\n')
|
|
52
83
|
}
|
|
84
|
+
if (err) return err
|
|
53
85
|
}
|
package/src/lib/runtimes.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// Canonical runtime list: https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
|
|
2
|
-
// Array order matters, newest (or most preferable) must always be at the top
|
|
3
|
-
let runtimes = {
|
|
4
|
-
node: [
|
|
5
|
-
'nodejs14.x',
|
|
6
|
-
'nodejs12.x',
|
|
7
|
-
'nodejs10.x',
|
|
8
|
-
],
|
|
9
|
-
python: [
|
|
10
|
-
'python3.9',
|
|
11
|
-
'python3.8',
|
|
12
|
-
'python3.7',
|
|
13
|
-
'python3.6',
|
|
14
|
-
'python2.7',
|
|
15
|
-
],
|
|
16
|
-
ruby: [
|
|
17
|
-
'ruby2.7',
|
|
18
|
-
'ruby2.5',
|
|
19
|
-
],
|
|
20
|
-
java: [
|
|
21
|
-
'java11',
|
|
22
|
-
'java8.al2',
|
|
23
|
-
'java8',
|
|
24
|
-
],
|
|
25
|
-
go: [
|
|
26
|
-
'go1.x',
|
|
27
|
-
],
|
|
28
|
-
dotnet: [
|
|
29
|
-
'dotnetcore3.1',
|
|
30
|
-
'dotnetcore2.1',
|
|
31
|
-
],
|
|
32
|
-
custom: [
|
|
33
|
-
'provided.al2',
|
|
34
|
-
'provided',
|
|
35
|
-
],
|
|
36
|
-
// Arc specific
|
|
37
|
-
deno: [
|
|
38
|
-
'deno'
|
|
39
|
-
],
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Human friendly shortcuts
|
|
43
|
-
let nodes = [ 'node', 'nodejs', 'node.js' ]
|
|
44
|
-
let pythons = [ 'python', 'py' ]
|
|
45
|
-
let rubies = [ 'ruby', 'rb' ]
|
|
46
|
-
let javas = [ 'java' ]
|
|
47
|
-
let gos = [ 'go', 'golang' ]
|
|
48
|
-
let dotnets = [ 'dotnet', '.net' ]
|
|
49
|
-
let customs = [ 'custom' ]
|
|
50
|
-
|
|
51
|
-
// Runtime interpolater
|
|
52
|
-
function getRuntime (name) {
|
|
53
|
-
if (typeof name === 'string') {
|
|
54
|
-
name = name.toLowerCase()
|
|
55
|
-
|
|
56
|
-
if (nodes.includes(name)) return runtimes.node[0]
|
|
57
|
-
if (runtimes.node.includes(name)) return name
|
|
58
|
-
|
|
59
|
-
if (pythons.includes(name)) return runtimes.python[0]
|
|
60
|
-
if (runtimes.python.includes(name)) return name
|
|
61
|
-
|
|
62
|
-
if (rubies.includes(name)) return runtimes.ruby[0]
|
|
63
|
-
if (runtimes.ruby.includes(name)) return name
|
|
64
|
-
|
|
65
|
-
if (javas.includes(name)) return runtimes.java[0]
|
|
66
|
-
if (runtimes.java.includes(name)) return name
|
|
67
|
-
|
|
68
|
-
if (gos.includes(name)) return runtimes.go[0]
|
|
69
|
-
if (runtimes.go.includes(name)) return name
|
|
70
|
-
|
|
71
|
-
if (dotnets.includes(name)) return runtimes.dotnet[0]
|
|
72
|
-
if (runtimes.dotnet.includes(name)) return name
|
|
73
|
-
|
|
74
|
-
if (customs.includes(name)) return runtimes.custom[0]
|
|
75
|
-
if (runtimes.custom.includes(name)) return name
|
|
76
|
-
|
|
77
|
-
if (runtimes.deno.includes(name)) return name
|
|
78
|
-
|
|
79
|
-
return name // Will be validated later
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
getRuntime.runtimes = runtimes
|
|
84
|
-
module.exports = getRuntime
|
package/src/validate/arn.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
let is = require('../lib/is')
|
|
2
|
-
|
|
3
|
-
// Validates Lambda layer / policy ARNs, prob can't be used for other kinds of ARN
|
|
4
|
-
module.exports = function validateARN ({ arn, region, loc }) {
|
|
5
|
-
if (!is.string(arn) ||
|
|
6
|
-
!arn.startsWith('arn:') ||
|
|
7
|
-
arn.split(':').length !== 8) {
|
|
8
|
-
/* istanbul ignore next */
|
|
9
|
-
let lambda = loc ? `in ${loc}` : ''
|
|
10
|
-
return `Invalid ARN${lambda}: ${arn}`
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
let parts = arn.split(':')
|
|
14
|
-
let layerRegion = parts[3]
|
|
15
|
-
if (region !== layerRegion) {
|
|
16
|
-
/* istanbul ignore next */
|
|
17
|
-
let lambda = loc ? ` - Lambda: ${loc}\n` : ''
|
|
18
|
-
let err = `Lambda layers must be in the same region as app\n` + lambda +
|
|
19
|
-
` - App region: ${region}\n` +
|
|
20
|
-
` - Layer ARN: ${arn}\n` +
|
|
21
|
-
` - Layer region: ${layerRegion}`
|
|
22
|
-
return err
|
|
23
|
-
}
|
|
24
|
-
}
|
package/src/validate/runtimes.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
let { lambdas } = require('../lib/pragmas')
|
|
2
|
-
let { runtimes } = require('../lib/runtimes')
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Runtime validator
|
|
6
|
-
*/
|
|
7
|
-
module.exports = function runtimeValidator (params, inventory, errors) {
|
|
8
|
-
|
|
9
|
-
let allRuntimes = Object.keys(runtimes).reduce((a, k) => a.concat(runtimes[k]), [])
|
|
10
|
-
let globalRuntime = inventory.aws?.runtime
|
|
11
|
-
if (globalRuntime && !allRuntimes.includes(globalRuntime)) {
|
|
12
|
-
errors.push(`Invalid project-level runtime: ${globalRuntime}`)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Walk the tree of layer configs, starting with @aws
|
|
16
|
-
Object.keys(inventory).forEach(i => {
|
|
17
|
-
let item = inventory[i]
|
|
18
|
-
if (lambdas.includes(i) && item) {
|
|
19
|
-
item.forEach(entry => {
|
|
20
|
-
let runtime = entry.config.runtime
|
|
21
|
-
if (runtime === globalRuntime) return
|
|
22
|
-
if (!allRuntimes.includes(runtime)) {
|
|
23
|
-
errors.push(`Invalid runtime: ${runtime} (@${i} ${entry.name})`)
|
|
24
|
-
}
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
}
|