Created
May 4, 2017 22:58
-
-
Save olivoil/7e42d1e7941c24a7872d8c0ecf296be8 to your computer and use it in GitHub Desktop.
prune lambda functions from serverless file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env node | |
| const AWS = require("aws-sdk"); | |
| const YAML = require("yamljs"); | |
| const ENV = process.env.NODE_ENV || "dev"; | |
| // it assumes you have AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in your environment | |
| const lambda = new AWS.Lambda({ | |
| region: process.env.AWS_REGION || "us-east-1", | |
| }); | |
| function exit(err) { | |
| if (err) console.log(err); | |
| process.exit(err ? 1 : 0); | |
| } | |
| async function prune() { | |
| const serverless = YAML.load("serverless.yml"); | |
| const functionNames = Object.keys(serverless.functions).map((n) => `${serverless.service}-${ENV}-${n}`); | |
| return series(functionNames.map((n) => pruneFunction(n))); | |
| } | |
| async function listVersions(name, marker, versions) { | |
| const prev = versions || []; | |
| const params = { FunctionName: name, MaxItems: 10000 }; | |
| if (marker) params.Marker = marker; | |
| let list = {Versions: [], NextMarker: ""}; | |
| try { | |
| list = await lambda.listVersionsByFunction(params).promise(); | |
| } catch(e) { | |
| console.log(`error fetching versions for ${name}: ${e.message}`); | |
| } | |
| const curr = prev.concat(list.Versions); | |
| if (list.NextMarker) { | |
| return listVersions(name, list.NextMarker, curr); | |
| } | |
| return curr; | |
| } | |
| async function pruneFunction(name, keep) { | |
| let keepLast = keep || 5; | |
| const versions = await listVersions(name); | |
| const sorted = versions.sort((v1, v2) => { | |
| if (v1.LastModified < v2.LastModified) { | |
| return 1; | |
| } else { | |
| if( v1.LastModified > v2.LastModified ) { | |
| return -1; | |
| } else { | |
| return 0; | |
| } | |
| } | |
| }); | |
| let listAliases = { Aliases: [] }; | |
| try { | |
| listAliases = await lambda.listAliases({ FunctionName: name, MaxItems: 10000 }).promise(); | |
| } catch (e) { | |
| console.log(`error fetching aliases for ${name}: ${e.message}`); | |
| } | |
| // keep any version that is pointed to by an alias | |
| const keepVersions = listAliases.Aliases.map((a) => a.FunctionVersion); | |
| const keeping = []; | |
| sorted.forEach((v) => { | |
| if ((v.Version == "$LATEST") || (keepVersions.includes(v.Version)) ) { | |
| keeping.push(v.Version); | |
| } | |
| else if (keepLast > 0) { | |
| keeping.push(v.Version); | |
| keepLast--; | |
| } | |
| }); | |
| const deleting = sorted.map((v) => v && keeping.includes(v.Version) ? null : v).filter((v) => v).reverse(); | |
| console.log(`${name}:`); | |
| console.log(`- keeping ${keeping.length} versions: ${keeping.join(", ")}`); | |
| console.log(`- deleting ${deleting.length} versions: ${deleting.map((v) => v.Version).join(", ")}`); | |
| return series(deleting.map((v) => { | |
| return lambda.deleteFunction({ FunctionName: v.FunctionName, Qualifier: v.Version }).promise(); | |
| })); | |
| } | |
| function series(arrayOfPromises) { | |
| const results = []; | |
| return arrayOfPromises.reduce((seriesPromise, promise) => { | |
| return seriesPromise.then(() => { | |
| return promise.then((result) => { | |
| results.push(result); | |
| }); | |
| }); | |
| }, Promise.resolve()) | |
| .then(() => { | |
| return results; | |
| }); | |
| } | |
| module.exports = exports.default = exports.prune = prune; | |
| if (require.main === module) { | |
| prune().then(() => exit()).catch(exit); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment