serverless-leo
Advanced tools
Comparing version 3.0.12-alpha.1 to 3.0.12-alpha.2
29
index.js
@@ -13,3 +13,3 @@ 'use strict' | ||
const { generateConfig, getConfigFullPath, populateEnvFromConfig, resolveConfigForLocal } = require('./lib/generateConfig') | ||
const { editConfig } = require("./lib/config-parameters") | ||
const { editConfig } = require('./lib/config-parameters') | ||
@@ -201,3 +201,3 @@ // TODO: sls create - Place tempates in memorable cdn location like https://dsco.io/aws-nodejs-leo-microservice | ||
const replacements = []; | ||
const replacements = [] | ||
Object.entries(tokens).map(([key, token]) => { | ||
@@ -210,4 +210,4 @@ let value = opts[key] | ||
replacements.push([token, value]) | ||
if (key === "rstreams-bus" && token.match(/-Bus-/)) { | ||
replacements.push([token.replace(/-Bus-.*$/, "-Bus"), value.replace(/-Bus-.*$/, "-Bus")]) | ||
if (key === 'rstreams-bus' && token.match(/-Bus-/)) { | ||
replacements.push([token.replace(/-Bus-.*$/, '-Bus'), value.replace(/-Bus-.*$/, '-Bus')]) | ||
} | ||
@@ -285,6 +285,6 @@ }) | ||
let opts = { ...this.serverless.pluginManager.cliOptions } | ||
await this.hooks["before:package:createDeploymentArtifacts"](); | ||
await this.hooks['before:package:createDeploymentArtifacts']() | ||
let webpackPlugin = this.serverless.pluginManager.plugins.find(s => s.constructor.name === 'ServerlessWebpack') | ||
let skipWebpack = (this.serverless.service.custom.leo || {}).skipWebpack !== false; | ||
let skipWebpack = (this.serverless.service.custom.leo || {}).skipWebpack !== false | ||
// Setup the node runner | ||
@@ -346,10 +346,10 @@ if (skipWebpack && opts.runner === 'node' && (this.serverless.service.provider.runtime || '').match(/^nodejs/)) { | ||
serverless.service.provider.environment = serverless.service.provider.environment || {}; | ||
serverless.service.provider.environment.RSF_INVOKE_STAGE = serverless.service.provider.stage; | ||
serverless.service.provider.environment = serverless.service.provider.environment || {} | ||
serverless.service.provider.environment.RSF_INVOKE_STAGE = serverless.service.provider.stage | ||
await resolveConfigForLocal(this.serverless, { | ||
stack: (serverless.service.provider.stackParameters || []).reduce((all, one) => { | ||
if (one != null) { | ||
all[one.ParameterKey] = one.ParameterValue; | ||
all[one.ParameterKey] = one.ParameterValue | ||
} | ||
return all; | ||
return all | ||
}, {}) | ||
@@ -443,3 +443,3 @@ }) | ||
'before:aws:deploy:deploy:createStack': async () => { | ||
// Create doesn't use stack parameters so we need to remove them | ||
// Create doesn't use stack parameters so we need to remove them | ||
// so the action doesn't fail | ||
@@ -449,7 +449,7 @@ let params = (this.serverless.service.provider.coreCloudFormationTemplate || {}).Parameters || {} | ||
this.serverless.service.provider.stackParameters = stackParams.filter(a => a.ParameterKey in params) | ||
this.origStackParams = stackParams; | ||
this.origStackParams = stackParams | ||
}, | ||
'before:aws:deploy:deploy:updateStack': async () => { | ||
// Create doesn't use stack parameters so we had to remove them | ||
// Create doesn't use stack parameters so we had to remove them | ||
// add them back so the action doesn't fail | ||
@@ -459,3 +459,2 @@ if (this.origStackParams != null) { | ||
} | ||
}, | ||
@@ -467,3 +466,3 @@ 'edit-config:run': async () => { | ||
generateConfig(file) | ||
}, | ||
} | ||
} | ||
@@ -470,0 +469,0 @@ } |
@@ -5,5 +5,4 @@ /* eslint-disable space-before-function-paren */ | ||
const path = require('path') | ||
const { fetchAll } = require("./utils"); | ||
const { fetchAll } = require('./utils') | ||
// Try to get serverless 3 version, if that fails try serverless 2 version | ||
@@ -17,4 +16,3 @@ // let resolveCfRefValue; | ||
async function resolveCfRefValue(provider, resourceLogicalId, sdkParams = {}) { | ||
let params = (provider.serverless.service.resources.Parameters || {}); | ||
let params = (provider.serverless.service.resources.Parameters || {}) | ||
if (resourceLogicalId in params) { | ||
@@ -33,6 +31,6 @@ return (provider.serverless.service.provider.stackParameters || {})[resourceLogicalId] | ||
(stackResource) => stackResource.LogicalResourceId === resourceLogicalId | ||
); | ||
if (targetStackResource) return targetStackResource.PhysicalResourceId; | ||
) | ||
if (targetStackResource) return targetStackResource.PhysicalResourceId | ||
if (result.NextToken) { | ||
return resolveCfRefValue(provider, resourceLogicalId, { NextToken: result.NextToken }); | ||
return resolveCfRefValue(provider, resourceLogicalId, { NextToken: result.NextToken }) | ||
} | ||
@@ -43,7 +41,6 @@ | ||
'CF_REF_RESOLUTION' | ||
); | ||
}); | ||
) | ||
}) | ||
} | ||
let ts | ||
@@ -89,4 +86,4 @@ try { | ||
function expandConfig(projectConfig, path) { | ||
if (projectConfig == null || typeof projectConfig != "object") { | ||
return projectConfig; | ||
if (projectConfig == null || typeof projectConfig !== 'object') { | ||
return projectConfig | ||
} | ||
@@ -169,17 +166,17 @@ let o = {} | ||
let collection = "TYPE"; | ||
let matchParts; | ||
let collection = 'TYPE' | ||
let matchParts | ||
if (matchParts = t.match(/\[\]$/)) { | ||
t = t.replace(/\[\]$/, ""); | ||
collection = "TYPE[]"; | ||
t = t.replace(/\[\]$/, '') | ||
collection = 'TYPE[]' | ||
} else if (matchParts = t.match(/(Map|Set|Array)<(.*?)>/)) { | ||
collection = `${matchParts[1]}<TYPE>`; | ||
t = matchParts[2].split(",").map(t => t.trim()); | ||
collection = `${matchParts[1]}<TYPE>` | ||
t = matchParts[2].split(',').map(t => t.trim()) | ||
} | ||
if (!Array.isArray(t)) { | ||
t = [t]; | ||
t = [t] | ||
} | ||
t = t.map(t => { | ||
if (!knownTypes[t]) { | ||
if (!t.startsWith("{")) { | ||
if (!t.startsWith('{')) { | ||
imports.add(t) | ||
@@ -190,23 +187,22 @@ } | ||
} | ||
return t; | ||
}).join(", ") | ||
return collection.replace("TYPE", t); | ||
return t | ||
}).join(', ') | ||
return collection.replace('TYPE', t) | ||
} else { | ||
let nextDepth = depth += spaces | ||
if (Array.isArray(field)) { | ||
// Get unique set of types in the array | ||
let r = Array.from(new Set(Object.entries(field).map(([key, value]) => { | ||
return getType(value, nextDepth); | ||
}))); | ||
return getType(value, nextDepth) | ||
}))) | ||
// Join them togethere if there is more than 1 | ||
let rLen = r.length; | ||
r = r.join("|"); | ||
let rLen = r.length | ||
r = r.join('|') | ||
if (rLen > 1) { | ||
r = `(${r})`; | ||
r = `(${r})` | ||
} | ||
// return array type | ||
return `${r}[]`; | ||
return `${r}[]` | ||
} else { | ||
@@ -387,3 +383,3 @@ let r = Object.entries(field).map(([key, value]) => { | ||
case 'cfr': v = { | ||
'Ref': value.key.replace(/\./g, "").replace(/\$\{.*?\}/g, "") | ||
'Ref': value.key.replace(/\./g, '').replace(/\$\{.*?\}/g, '') | ||
}; break | ||
@@ -398,3 +394,3 @@ case 'ssm': v = { 'Fn::Sub': `{{resolve:ssm:${value.key}}}` }; break | ||
let parts = value.key.split('.') | ||
parts = [parts[0], 'SecretString'].concat(parts.splice(1).join(".")); | ||
parts = [parts[0], 'SecretString'].concat(parts.splice(1).join('.')) | ||
v = { 'Fn::Sub': `{{resolve:secretsmanager:${parts.join(':')}}}` } | ||
@@ -409,2 +405,10 @@ } | ||
lookups.push(v) | ||
} else if (value != null && Array.isArray(value)) { | ||
let r = value.map(v => { | ||
if (v == null || typeof (v) !== 'object') { | ||
return v | ||
} | ||
return getConfigReferences(v, useSecretsManager, lookups, permissions).output | ||
}) | ||
output[key] = r | ||
} else if (value != null && typeof value === 'object') { | ||
@@ -429,16 +433,16 @@ let r = getConfigReferences(value, useSecretsManager, lookups, permissions) | ||
async function resolveConfigForLocal(serverless, cache = {}) { | ||
let fullStage = `${serverless.providers.aws.getRegion()}-${serverless.service.provider.environment.RSF_INVOKE_STAGE}`; | ||
let configFromCache = false; | ||
let serviceDir = serverless.config.serviceDir || serverless.config.servicePath; | ||
let configFileCache = path.resolve(serviceDir, `.rsf/config-${fullStage}.json`); | ||
let fullStage = `${serverless.providers.aws.getRegion()}-${serverless.service.provider.environment.RSF_INVOKE_STAGE}` | ||
let configFromCache = false | ||
let serviceDir = serverless.config.serviceDir || serverless.config.servicePath | ||
let configFileCache = path.resolve(serviceDir, `.rsf/config-${fullStage}.json`) | ||
if (fs.existsSync(configFileCache)) { | ||
let stat = fs.statSync(configFileCache); | ||
let duration = Math.floor((Date.now() - stat.mtimeMs) / 1000); | ||
let stat = fs.statSync(configFileCache) | ||
let duration = Math.floor((Date.now() - stat.mtimeMs) / 1000) | ||
// Default cache duration is 30 min | ||
let validCacheDuration = (+process.env.RSF_CACHE_SECONDS) || 1800; | ||
let validCacheDuration = (+process.env.RSF_CACHE_SECONDS) || 1800 | ||
if (duration < validCacheDuration) { | ||
try { | ||
serverless.service.provider.environment.RSF_CONFIG = JSON.stringify(module.require(configFileCache)); | ||
configFromCache = true; | ||
serverless.service.provider.environment.RSF_CONFIG = JSON.stringify(module.require(configFileCache)) | ||
configFromCache = true | ||
} catch (e) { | ||
@@ -457,23 +461,24 @@ // Error getting cache | ||
...cache | ||
}; | ||
} | ||
// Resolve config env var | ||
let rsfConfigEnvTemplate = serverless.service.provider.environment && serverless.service.provider.environment.RSF_CONFIG; | ||
let rsfConfigEnvTemplate = serverless.service.provider.environment && serverless.service.provider.environment.RSF_CONFIG | ||
if (!configFromCache && rsfConfigEnvTemplate) { | ||
let v = await resolveFnSub(rsfConfigEnvTemplate, serverless, cache); | ||
serverless.service.provider.environment.RSF_CONFIG = v; | ||
console.log('rsfConfigEnvTemplate:', rsfConfigEnvTemplate) | ||
let v = await resolveFnSub(rsfConfigEnvTemplate, serverless, cache) | ||
serverless.service.provider.environment.RSF_CONFIG = v | ||
} | ||
let busConfigFromCache = false; | ||
let busConfigFileCache = path.resolve(serviceDir, `.rsf/bus-config-${fullStage}.json`); | ||
let busConfigFromCache = false | ||
let busConfigFileCache = path.resolve(serviceDir, `.rsf/bus-config-${fullStage}.json`) | ||
if (fs.existsSync(busConfigFileCache)) { | ||
let stat = fs.statSync(busConfigFileCache); | ||
let duration = Math.floor((Date.now() - stat.mtimeMs) / 1000); | ||
let stat = fs.statSync(busConfigFileCache) | ||
let duration = Math.floor((Date.now() - stat.mtimeMs) / 1000) | ||
// Default cache duration is 30 min | ||
let validCacheDuration = (+process.env.RSF_CACHE_SECONDS) || 1800; | ||
let validCacheDuration = (+process.env.RSF_CACHE_SECONDS) || 1800 | ||
if (duration < validCacheDuration) { | ||
try { | ||
serverless.service.provider.environment.RSTREAMS_CONFIG = JSON.stringify(module.require(busConfigFileCache)); | ||
busConfigFromCache = true; | ||
serverless.service.provider.environment.RSTREAMS_CONFIG = JSON.stringify(module.require(busConfigFileCache)) | ||
busConfigFromCache = true | ||
} catch (e) { | ||
@@ -486,17 +491,16 @@ // Error getting cache | ||
// Resolve bus env config if it exists | ||
let rstreamsConfigEnvTemplate = serverless.service.provider.environment && serverless.service.provider.environment.RSTREAMS_CONFIG; | ||
let rstreamsConfigEnvTemplate = serverless.service.provider.environment && serverless.service.provider.environment.RSTREAMS_CONFIG | ||
if (!busConfigFromCache && rstreamsConfigEnvTemplate) { | ||
let v = await resolveFnSub(rstreamsConfigEnvTemplate, serverless, cache); | ||
serverless.service.provider.environment.RSTREAMS_CONFIG = v; | ||
fs.mkdirSync(path.dirname(busConfigFileCache), { recursive: true }); | ||
fs.writeFileSync(busConfigFileCache, JSON.stringify(JSON.parse(v), null, 2)); | ||
let v = await resolveFnSub(rstreamsConfigEnvTemplate, serverless, cache) | ||
serverless.service.provider.environment.RSTREAMS_CONFIG = v | ||
fs.mkdirSync(path.dirname(busConfigFileCache), { recursive: true }) | ||
fs.writeFileSync(busConfigFileCache, JSON.stringify(JSON.parse(v), null, 2)) | ||
} | ||
// Resolve bus env secret if it exists | ||
let rstreamsConfigEnvSecretTemplate = serverless.service.provider.environment && serverless.service.provider.environment.RSTREAMS_CONFIG_SECRET; | ||
let rstreamsConfigEnvSecretTemplate = serverless.service.provider.environment && serverless.service.provider.environment.RSTREAMS_CONFIG_SECRET | ||
if (rstreamsConfigEnvSecretTemplate) { | ||
let v = await resolveFnSub(rstreamsConfigEnvSecretTemplate, serverless, cache); | ||
serverless.service.provider.environment.RSTREAMS_CONFIG_SECRET = v; | ||
let v = await resolveFnSub(rstreamsConfigEnvSecretTemplate, serverless, cache) | ||
serverless.service.provider.environment.RSTREAMS_CONFIG_SECRET = v | ||
} | ||
} | ||
@@ -506,20 +510,20 @@ | ||
secretsmanager: async (provider, key, cache) => { | ||
let parts = key.split(":"); | ||
let id = parts.shift(); | ||
let last = parts.pop(); | ||
let value; | ||
let parts = key.split(':') | ||
let id = parts.shift() | ||
let last = parts.pop() | ||
let value | ||
if (id in cache.sm) { | ||
value = cache.sm[id]; | ||
value = cache.sm[id] | ||
} else { | ||
value = await provider.request("SecretsManager", "getSecretValue", { SecretId: id }); | ||
cache.sm[id] = value; | ||
value = await provider.request('SecretsManager', 'getSecretValue', { SecretId: id }) | ||
cache.sm[id] = value | ||
} | ||
return parts.reduce((o, k) => { | ||
let v = o[k] || {}; | ||
if (typeof v === "string") { | ||
v = JSON.parse(v); | ||
let v = o[k] || {} | ||
if (typeof v === 'string') { | ||
v = JSON.parse(v) | ||
} | ||
return v; | ||
}, value)[last]; | ||
return v | ||
}, value)[last] | ||
}, | ||
@@ -530,5 +534,5 @@ ssm: async (provider, key, cache) => { | ||
} else { | ||
let value = await provider.request("SSM", "getParameter", { Name: key }); | ||
cache.ssm[key] = value.Parameter.Value; | ||
return value.Parameter.Value; | ||
let value = await provider.request('SSM', 'getParameter', { Name: key }) | ||
cache.ssm[key] = value.Parameter.Value | ||
return value.Parameter.Value | ||
} | ||
@@ -538,23 +542,23 @@ }, | ||
if (Object.keys(cache.cf).length === 0) { | ||
let allCfExports = await fetchAll(t => provider.request("CloudFormation", "listExports", { NextToken: t })); | ||
let allCfExports = await fetchAll(t => provider.request('CloudFormation', 'listExports', { NextToken: t })) | ||
allCfExports.Exports.forEach(v => { | ||
cache.cf[v.Name] = v.Value; | ||
}); | ||
cache.cf[v.Name] = v.Value | ||
}) | ||
} | ||
return cache.cf[key]; | ||
return cache.cf[key] | ||
}, | ||
cfr: async (provider, key, cache) => { | ||
if (!(key in cache.cfr)) { | ||
let [stack, resource] = key.split("."); | ||
cache.cfr[key] = await resolveCfRefValue(provider, resource, { StackName: stack }); | ||
let [stack, resource] = key.split('.') | ||
cache.cfr[key] = await resolveCfRefValue(provider, resource, { StackName: stack }) | ||
} | ||
return cache.cfr[key]; | ||
return cache.cfr[key] | ||
}, | ||
stack: async (provider, key, cache) => { | ||
if (!(key in cache.stack)) { | ||
cache.stack[key] = await resolveCfRefValue(provider, key); | ||
cache.stack[key] = await resolveCfRefValue(provider, key) | ||
} | ||
return cache.stack[key]; | ||
return cache.stack[key] | ||
} | ||
}; | ||
} | ||
@@ -565,59 +569,59 @@ async function resolveFnSub(fnSub, serverless, cache) { | ||
if (one != null) { | ||
let paramDef = (serverless.service.resources.Parameters || {})[one.ParameterKey]; | ||
let paramDef = (serverless.service.resources.Parameters || {})[one.ParameterKey] | ||
if (paramDef && paramDef.Type.match(/AWS::SSM::Parameter/)) { | ||
all[one.ParameterKey] = `{{resolve:ssm:${one.ParameterValue}}}` | ||
} else { | ||
all[one.ParameterKey] = one.ParameterValue; | ||
all[one.ParameterKey] = one.ParameterValue | ||
} | ||
} | ||
return all; | ||
return all | ||
}, {}), | ||
...serverless.service.resources.Resources, | ||
}; | ||
if (fnSub != null && typeof fnSub === "object" && fnSub["Fn::Sub"]) { | ||
fnSub = fnSub["Fn::Sub"]; | ||
...serverless.service.resources.Resources | ||
} | ||
if (fnSub != null && typeof fnSub === 'object' && fnSub['Fn::Sub']) { | ||
fnSub = fnSub['Fn::Sub'] | ||
} | ||
let template = fnSub; | ||
let template = fnSub | ||
if (Array.isArray(fnSub)) { | ||
let [t, l] = fnSub; | ||
template = t; | ||
lookups = l; | ||
let [t, l] = fnSub | ||
template = t | ||
lookups = l | ||
} | ||
Object.entries({ | ||
"AWS::Region": serverless.providers.aws.getRegion(), | ||
"AWS::StackName": serverless.providers.aws.naming.getStackName() | ||
'AWS::Region': serverless.providers.aws.getRegion(), | ||
'AWS::StackName': serverless.providers.aws.naming.getStackName() | ||
}).forEach(([key, value]) => { | ||
lookups[key] = value; | ||
}); | ||
let entries = Object.entries(lookups); | ||
lookups[key] = value | ||
}) | ||
let entries = Object.entries(lookups) | ||
for (let i = 0; i < entries.length; i++) { | ||
let [key, value] = entries[i]; | ||
if (value != null && typeof value === "object" && value["Fn::Sub"]) { | ||
value = await resolveFnSub(value["Fn::Sub"], serverless, cache); | ||
let [key, value] = entries[i] | ||
if (value != null && typeof value === 'object' && value['Fn::Sub']) { | ||
value = await resolveFnSub(value['Fn::Sub'], serverless, cache) | ||
} | ||
if (value != null && typeof value === "object") { | ||
if (value != null && typeof value === 'object') { | ||
if (value.Ref) { | ||
let preValue = value.Ref; | ||
value = await resolveServices.stack(serverless.providers.aws, preValue, cache); | ||
} else if (value["Fn::ImportValue"]) { | ||
let preValue = await resolveFnSub(value["Fn::ImportValue"], serverless, cache); | ||
value = await resolveServices.cf(serverless.providers.aws, preValue, cache); | ||
let preValue = value.Ref | ||
value = await resolveServices.stack(serverless.providers.aws, preValue, cache) | ||
} else if (value['Fn::ImportValue']) { | ||
let preValue = await resolveFnSub(value['Fn::ImportValue'], serverless, cache) | ||
value = await resolveServices.cf(serverless.providers.aws, preValue, cache) | ||
} | ||
} else if (typeof value === "string") { | ||
let [, service, key] = (value.match(/{{resolve:(secretsmanager|ssm):(.*)}}$/) || []); | ||
} else if (typeof value === 'string') { | ||
let [, service, key] = (value.match(/{{resolve:(secretsmanager|ssm):(.*)}}$/) || []) | ||
if (service && resolveServices[service]) { | ||
value = await resolveServices[service](serverless.providers.aws, key, cache); | ||
value = await resolveServices[service](serverless.providers.aws, key, cache) | ||
} | ||
} | ||
lookups[key] = value; | ||
lookups[key] = value | ||
} | ||
return template.replace(/\${(.*?)}/g, (_, key) => { | ||
let v = lookups[key]; | ||
if (typeof v !== "string") { | ||
v = JSON.stringify(v); | ||
let v = lookups[key] | ||
if (typeof v !== 'string') { | ||
v = JSON.stringify(v) | ||
} | ||
return v; | ||
}); | ||
return v | ||
}) | ||
} | ||
@@ -632,4 +636,3 @@ | ||
let { output, lookups, permissions } = getConfigReferences(config, useSecretsManager) | ||
let hasConfig = Object.keys(output || {}).length > 0; | ||
let hasConfig = Object.keys(output || {}).length > 0 | ||
let params = {}; | ||
@@ -711,3 +714,2 @@ // Find Stack Parameters | ||
let rsfConfigName = { | ||
@@ -745,5 +747,5 @@ 'Fn::Sub': 'rsf-config-${AWS::StackName}-${AWS::Region}' | ||
serverless.service.custom.leo.rsfConfigReplicationRegions[key]) { | ||
values = serverless.service.custom.leo.rsfConfigReplicationRegions[key]; | ||
values = serverless.service.custom.leo.rsfConfigReplicationRegions[key] | ||
if (!Array.isArray(values)) { | ||
values = [values]; | ||
values = [values] | ||
} | ||
@@ -755,4 +757,4 @@ } | ||
})) | ||
}; | ||
return a; | ||
} | ||
return a | ||
}, {}) | ||
@@ -857,3 +859,3 @@ } | ||
}, | ||
ReplicaRegions: { "Fn::FindInMap": ["RSFReplicaMap", { "Ref": "AWS::Region" }, "values"] }, | ||
ReplicaRegions: { 'Fn::FindInMap': ['RSFReplicaMap', { 'Ref': 'AWS::Region' }, 'values'] }, | ||
Tags: [{ | ||
@@ -860,0 +862,0 @@ Key: 'service', |
{ | ||
"name": "serverless-leo", | ||
"version": "3.0.12-alpha.1", | ||
"version": "3.0.12-alpha.2", | ||
"description": "Serverless plugin for leo microservices", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
145379
2875