Skip to content

Instantly share code, notes, and snippets.

@johncmckim
Last active May 1, 2017 17:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johncmckim/e35e2861bbce8612a88953f791d0493b to your computer and use it in GitHub Desktop.
Save johncmckim/e35e2861bbce8612a88953f791d0493b to your computer and use it in GitHub Desktop.
Prune Lambda Functions - PLEASE REVIEW AND USE AT YOUR OWN RISK
{
"dependencies": {
"aws-sdk": "^2.7.10",
"bluebird": "^3.4.6",
"lodash": "^4.17.2",
"moment": "^2.17.1"
}
}
'use strict';
const BbPromise = require('bluebird');
const AWS = require('aws-sdk');
const _ = require('lodash');
const moment = require('moment');
AWS.config.update({
region: process.env.AWS_REGION,
credentials: new AWS.SharedIniFileCredentials({
profile: process.env.AWS_PROFILE
})
});
const lambda = new AWS.Lambda();
const deleteLambdaVersion = (functionName, version) => {
if(!version) throw new Error(`Don't delete production!`)
console.log(`Deleting ${functionName}:${version}`);
const params = {
FunctionName: functionName,
Qualifier: version,
};
return new BbPromise((resolve, reject) => {
lambda.deleteFunction(params, function(err, result) {
if (err) reject(err);
else resolve(result);
});
});
}
const requestVersionsPage = (functionName, marker) => {
const params = {
FunctionName: functionName,
Marker: marker,
};
return new BbPromise((resolve, reject) => {
lambda.listVersionsByFunction(params, (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
}
const listVersions = (functionName, versions, marker) => requestVersionsPage(functionName, marker)
.then(result => {
const versionAccum = (versions || []).concat(result.Versions);
if (result.NextMarker) {
return listVersions(functionName, versionAccum, result.NextMarker);
}
return versionAccum;
});
const listAliases = (functionName) => {
var params = {
FunctionName: functionName,
// FunctionVersion: 'STRING_VALUE',
// Marker: 'STRING_VALUE',
MaxItems: 100
};
return new BbPromise((resolve, reject) => {
lambda.listAliases(params, function (err, result) {
if (err) reject(err);
else resolve(result.Aliases);
});
});
}
const requestFunctionsPage = (marker) => {
const params = {
Marker: marker,
};
return new BbPromise((resolve, reject) => {
lambda.listFunctions(params, function(err, data) {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
const listFunctions = (functions, marker) => requestFunctionsPage(marker).then((result) => {
const functionsAccum = (functions || []).concat(result.Functions);
if (result.NextMarker) {
return listFunctions(functionsAccum, result.NextMarker);
}
return functionsAccum;
});
const KEEP_X_VERSIONS = 15;
const KEEP_DAYS = 7;
console.log(`Listing functions`);
listFunctions()
.then((functions) => functions.map(f => f.FunctionName))
.then((functions) => {
console.log(`Found ${functions.length} functions`);
console.log(functions);
return functions;
})
.map((functionName) => {
console.log(`Listing versions for function ${functionName}`);
return BbPromise.all([
listAliases(functionName),
listVersions(functionName),
]).spread((aliases, functions) => {
const aliasVersions = aliases.map(a => a.FunctionVersion);
const sortedFunctions = _.orderBy(functions, func => {
if (func.Version === '$LATEST') return 1 * 1000 * 1000;
return parseInt(func.Version, 10);
}, 'desc');
const toDelete = _.filter(sortedFunctions, (func, i) => {
if (func.Version === '$LATEST') return false;
if (i <= KEEP_X_VERSIONS) return false;
const daysOld = moment().diff(moment(func.LastModified), 'days', true);
if(daysOld < KEEP_DAYS) return false;
return !_.includes(aliasVersions, func.Version);
});
const codeSize = toDelete.reduce((total, func) => total + func.CodeSize, 0);
console.log(`Deleting ${toDelete.length} versions of size ${codeSize} bytes`);
return BbPromise.map(toDelete, (func) => deleteLambdaVersion(functionName, func.Version), {
concurrency: 5
}).catch(err => {
console.error(err);
});
});
}, { concurrency: 1 })
.catch(err => {
console.error(err);
});
@johncmckim
Copy link
Author

Again, use at your own risk and please don't delete prod.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment