serverless-cf-vars
Version:
Allows you to use Cloudformation pseudo parameters and substitute in other variables in your serverless.yml.
92 lines (85 loc) • 2.51 kB
JavaScript
/*eslint no-template-curly-in-string: "off"*/
/*eslint no-cond-assign: "off"*/
var _ = require('lodash')
var keyStem = 'serverlesscfvarsplugin'
var searchRe = new RegExp(keyStem + '(\\d+)')
/**
* Some plugins try to clean up ${}-tags
* This step finds our #{} and replace them with alpha numeric text.
* This should allow our tags to slip past "helpful" cleanup attempts.
*/
function step0(dictionary, insideSub, ivars = {}) {
const vars = Object.assign({}, ivars)
const resources = _.transform(dictionary, function(acc, val, key) {
insideSub = insideSub || key === 'Fn::Sub'
if (_.isPlainObject(val) || _.isArray(val)) {
const result = step0(val, insideSub, vars)
Object.assign(vars, result.vars)
acc[key] = result.resources
return
}
if (typeof val === 'string') {
var matches, cfkey
while (matches = val.match(/#{([^}]+)}/)) {
cfkey = keyStem + Object.keys(vars).length
vars[cfkey] = matches[1]
val = val.replace(/#{[^}]+}/, cfkey)
}
if (cfkey) {
acc[key] = insideSub ? val : { 'Fn::Sub': val }
return
}
}
acc[key] = val
})
return {resources, vars}
}
/**
* Let's convert the strings that step0 produced into ${}
*/
function step1(dictionary, vars) {
const resources = _.transform(dictionary, function(acc, val, key) {
if (_.isPlainObject(val) || _.isArray(val)) {
acc[key] = step1(val, vars)
return
}
if (typeof val === 'string') {
var matches, cfkey, cfvalue
while (matches = val.match(searchRe)) {
cfkey = keyStem + matches[1]
cfvalue = vars[cfkey]
val = val.replace(cfkey, '${'+cfvalue+'}')
}
if (cfkey) {
acc[key] = val
return
}
}
acc[key] = val
})
return resources
}
/**
* Custom resources aren't available until now, so they haven't been replaced in step0.
* Let's replace any #{} that exist at this point.
*/
function step2(dictionary, insideSub) {
return _.transform(dictionary, function(acc, val, key) {
insideSub = insideSub || key === 'Fn::Sub'
if (_.isPlainObject(val) || _.isArray(val)) {
acc[key] = step2(val, insideSub)
return
}
if (typeof val === 'string' && val.search(/#{([^}]+)}/) !== -1) {
const newValue = val.replace(/#{([^}]+)}/g, '${$1}')
acc[key] = insideSub ? newValue : { 'Fn::Sub': newValue }
return
}
acc[key] = val
})
}
module.exports = {
step0,
step1,
step2
}