From 6ca429118900b6bfdeb490d6be2bfd1db5831e69 Mon Sep 17 00:00:00 2001 From: Benn Bollay Date: Mon, 21 Jan 2019 16:38:17 -0800 Subject: [PATCH] Add s3remove hooks to clean up Automatically remove created S3 buckets, and all of their contents on a `sls remove` or `sls s3remove` trigger. --- index.js | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 61615da..706a10b 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,7 @@ const fs = require('fs'); const path = require('path'); const mime = require('mime-types'); const BbPromise = require('bluebird'); +const messagePrefix = 'S3 Deploy: '; const globOpts = { nodir: true @@ -43,12 +44,30 @@ class Assets { shortcut: 'b' } } + }, + s3remove: { + usage: 'Remove assets from S3 buckets', + lifecycleEvents: [ + 'remove' + ], + options: { + verbose: { + usage: 'Increase verbosity', + shortcut: 'v' + }, + bucket: { + usage: 'Limit the removal to a specific bucket', + shortcut: 'b' + } + } } }; this.hooks = { 's3deploy:deploy': () => Promise.resolve().then(this.deployS3.bind(this)), - 'after:deploy:finalize': () => Promise.resolve().then(this.afterDeploy.bind(this)) + 'after:deploy:finalize': () => Promise.resolve().then(this.afterDeploy.bind(this)), + 's3remove:remove': () => Promise.resolve().then(this.removeS3.bind(this)), + 'before:remove:remove': () => Promise.resolve().then(this.beforeRemove.bind(this)) }; } @@ -58,7 +77,7 @@ class Assets { */ log(message) { if(this.options.verbose || process.env.SLS_DEBUG) { - this.serverless.cli.log(message); + this.serverless.cli.log(`${messagePrefix} ${message}`); } } @@ -68,6 +87,12 @@ class Assets { } } + beforeRemove() { + if(this.config.auto) { + this.removeS3(); + } + } + listStackResources(resources, nextToken) { resources = resources || []; return this.provider.request('CloudFormation', 'listStackResources', { StackName: this.provider.naming.getStackName(), NextToken: nextToken }) @@ -131,6 +156,19 @@ class Assets { }); } + removeBucket(bucket) { + console.log(`Removing bucket`, bucket); + const deleteParams = { + Bucket: bucket, + }; + + return this.provider.request('S3', 'deleteBucket', deleteParams) + .then(() => { + this.log(`Did it fail?`) + return + }); + } + deployS3() { let assetSets = this.config.targets; @@ -195,6 +233,31 @@ class Assets { ) }) } + + removeS3() { + let assetSets = this.config.targets; + + // Read existing stack resources so we can resolve references if necessary + return this.listStackResources() + .then(resources => { + // Process asset sets in parallel (up to 3) + return BbPromise.map(assetSets, assets => { + const prefix = assets.prefix || ''; + // Try to resolve the bucket name + return this.resolveBucket(resources, assets.bucket) + .then((bucket) => { + this.log(`Emptying bucket`) + return this.emptyBucket(bucket, prefix) + .then(() => { + this.log(`Removing Bucket: ${bucket}:${prefix}`) + return this.removeBucket(bucket); + }); + }) + }, + { concurrency: 3 } + ) + }) + } } module.exports = Assets;