diff --git a/package.json b/package.json index 849750a..fc62a44 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@valiton/aws-param-inject", - "version": "1.0.2", + "version": "1.0.3", "description": "Simple tool to fetch and inject parameters from AWS SSM into a string.", "bin": "src/index.js", "main": "src/inject-ssm-params.js", diff --git a/src/inject-ssm-params.js b/src/inject-ssm-params.js index 95129a3..2262b9b 100644 --- a/src/inject-ssm-params.js +++ b/src/inject-ssm-params.js @@ -2,11 +2,16 @@ const AWS = require("aws-sdk"); const ssm = new AWS.SSM(); +// aws has a hard limit on the number of keys it can return and errors of there +// are too many https://amzn.to/2QhXRTf +const keyPerRequestLimit = 10; const ssmPattern = /\$\{ssm:.*?\}/g; const extractKey = match => match.slice(6, -1); -const responseToMap = data => - data.Parameters.reduce( +const responseToParams = data => data.Parameters; + +const paramsToMap = params => + params.reduce( (acc, current) => ({ ...acc, [current.Name]: current.Value }), {} ); @@ -17,6 +22,16 @@ const makeError = invalidParameters => { return new Error(errMsg); }; +const createChunks = (chunkSize, array) => { + const numberOfChunks = Math.ceil(array.length / chunkSize); + return Array.from({ length: numberOfChunks }, (_, index) => { + const start = index * chunkSize; + return array.slice(index * chunkSize, start + chunkSize); + }); +}; + +const flatten = arr => arr.reduce((acc, current) => acc.concat(current), []); + const fetchParameters = names => ssm .getParameters({ Names: names, WithDecryption: true }) @@ -24,14 +39,18 @@ const fetchParameters = names => .then( data => data.InvalidParameters.length === 0 - ? Promise.resolve(responseToMap(data)) + ? Promise.resolve(responseToParams(data)) : Promise.reject(makeError(data.InvalidParameters)) ); const replaceParameters = input => paramsMap => input.replace(ssmPattern, match => paramsMap[extractKey(match)]); -module.exports = input => - Promise.resolve(input.match(ssmPattern).map(extractKey)) - .then(fetchParameters) +module.exports = input => { + const names = input.match(ssmPattern).map(extractKey); + const requests = createChunks(keyPerRequestLimit, names).map(fetchParameters); + return Promise.all(requests) + .then(flatten) + .then(paramsToMap) .then(replaceParameters(input)); +};