Skip to content

Instantly share code, notes, and snippets.

@gbleu
Last active April 8, 2016 15:45
Show Gist options
  • Save gbleu/a30ccccb223650a50f04 to your computer and use it in GitHub Desktop.
Save gbleu/a30ccccb223650a50f04 to your computer and use it in GitHub Desktop.
Delete Old Elasticbeanstalk Versions
var AWS = require('aws-sdk');
AWS.config.region = 'eu-west-1';
var elasticbeanstalk = new AWS.ElasticBeanstalk({apiVersion: '2010-12-01'});
// Restrict the applications to clean
var applicationNames = [];
var maxVersions = 10;
function listApplications(params, retries, callback) {
// console.info('# List applications ...');
var _params = { ApplicationNames: applicationNames };
elasticbeanstalk.describeApplications(_params, function(err, data) {
if (err) {
handleError(err, listApplications, params, retries, callback);
} else {
// console.info('# ' + data.Applications.length + ' applications found');
callback(null, data.Applications);
}
});
}
function listRunningVersions(params, retries, callback) {
// console.info('## ' + params.ApplicationName + ' : list running versions ...');
elasticbeanstalk.describeEnvironments(params, function(err, data) {
if (err) {
handleError(err, listRunningVersions, params, retries, callback);
} else {
var runningVersions = data.Environments.map(function(environment) {
return environment.VersionLabel;
});
// console.info('## ' + params.ApplicationName + ' : ' + runningVersions.length + ' running versions found');
callback(null, runningVersions);
}
});
}
function listApplicationVersions(params, retries, callback) {
// console.info('## ' + params.ApplicationName + ' : list versions ...');
elasticbeanstalk.describeApplicationVersions(params, function(err, data) {
if (err) {
handleError(err, listApplicationVersions, params, retries, callback);
} else {
// console.info('## ' + params.ApplicationName + ' : ' + data.ApplicationVersions.length + ' versions found');
callback(null, data.ApplicationVersions);
}
});
}
function deleteApplicationVersion(params, retries, callback) {
console.info('#### ' + params.ApplicationName + ' : delete version ' + params.VersionLabel + ' ...');
elasticbeanstalk.deleteApplicationVersion(params, function(err, data) {
if (err) {
handleError(err, deleteApplicationVersion, params, retries, callback);
} else {
console.info('#### ' + params.ApplicationName + ' : version ' + params.VersionLabel + ' deleted');
callback(null, data);
}
});
}
var maxRetries = 100, cap = 10000, base = 100;
function expo(n) {
return Math.min(cap, Math.pow(2, n) * base);
}
function rand(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function retry(n) {
return n <= maxRetries;
}
function delay(n) {
var v = expo(n);
return v/2 + rand(0, v/2);
}
function handleError(err, self, params, retries, callback) {
if(err.retryable && retry(retries)) {
var _delay = delay(retries);
// console.log('# Retry ' + retries + ' sleep ' + _delay + 'ms');
setTimeout(function() {
self(params, retries + 1, callback);
}, _delay);
} else {
console.error(err);
callback(err);
}
}
exports.handler = function(event, context) {
// Debug util to test outside of aws
// var context = {
// succeed: function(s) { console.log(s); },
// fail: function(s) { console.error(s); }
// };
listApplications({}, 1, function(err, apps){
if(!err) {
var appsToProcess = apps;
var versionsToDelete = [];
apps.forEach(function (app) {
listRunningVersions({ ApplicationName: app.ApplicationName }, 1, function(err2, runningVersions){
if(!err2) {
var allVersionsCount = 1, orphanVersionsCount = 1;
listApplicationVersions({ ApplicationName: app.ApplicationName, VersionLabels: app.Versions }, 1, function(err3, appVersions){
if(!err3) {
appVersions.forEach(function (appVersion) {
var runningVersion = runningVersions.indexOf(appVersion.VersionLabel) !== -1;
console.info('### ' + appVersion.ApplicationName + ' : ' + allVersionsCount + (runningVersion ? '*' : ' ') + ' : ' + appVersion.VersionLabel);
if(!runningVersion) {
if(orphanVersionsCount > maxVersions) {
versionsToDelete.push({ app: appVersion.ApplicationName, ver: appVersion.VersionLabel });
}
orphanVersionsCount++;
}
allVersionsCount++;
});
appsToProcess.splice(appsToProcess.indexOf(app), 1);
if(!appsToProcess.length) {
if(versionsToDelete.length) {
versionsToDelete.forEach(function (versionToDelete) {
deleteApplicationVersion({ ApplicationName: versionToDelete.app, VersionLabel: versionToDelete.ver, DeleteSourceBundle: true }, 1, function(err4, data){
if(!err4) {
versionsToDelete.splice(versionsToDelete.indexOf(versionToDelete), 1);
if(!versionsToDelete.length) {
context.succeed('All versions to delete have been deleted');
}
} else {
context.fail(err4);
}
});
});
} else {
context.succeed('Nothing to delete');
}
}
} else {
context.fail(err3);
}
});
} else {
context.fail(err2);
}
});
});
} else {
context.fail(err);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment