Node.js
AWS

[AWS]S3のバケットをまとめて削除する

はじめに

AWSを使ってインターンの運営をしているのですが、インターンに参加している人全員のS3バケットがどんどん溜まってしまいます。そんな時やっぱ掃除しなきゃダメだよねという話になり、S3のバケットを一気に削除するスクリプトを書いてみました。

方法

AWS SDKをnodejsで実行することによって実装します。動作環境は以下になります。

  • MacOS Sierra 10.12.4
  • Node.js v6.10.2

S3について

概要

念のためS3について説明しますが、簡単にいうとAWS上にいろんなファイルをおけるストレージサービスです。HTMLファイルなどを置いて静的ウェブホスティングというものをすることによって、静的なウェブサイトを作成することも可能です。
ちなみになぜS3というかというとSimple Storage Serviceの略だからだそうです。試したい方は以下のURLから。
Amazon S3

バケット

S3にはストレージの単位としてバケットというものが用意されています。インターンでは、一人一人のバケットを作成することによって、個人のフロントエンドのアプリケーションを実現していました。

オブジェクト

バケットの中にあるファイルをS3ではObjectと表現します。例えば、index.htmlというファイルとかも全てObjectとなるわけです。そしてこのオブジェクトにはKeyというものが付与されています。Keyは実際にはバケットのルートディレクトリからの絶対パスになります。

削除方法

次の手順で実装します。
S3の仕様上、中身が入っているバケットは中身のファイルを全て削除した状態でないと削除できないので、中身を削除してからバケットを削除します。

  1. 削除したくないバケット名の配列を定義する
  2. AWSアカウントのS3の全てのバケットを取得する
  3. 削除するバケットに入っているファイルのKeyを取得する
  4. 3で取得したKeyを元にObjectを削除する
  5. バケット自体を削除する

下準備

AWSアカウントのクレデンシャル情報をaws configureで設定してください。
詳しくは割愛します。

ソースコード(スクリプト)

s3-delete.js
const AWS = require('aws-sdk');
const s3 = new AWS.S3({region: 'ap-northeast-1'});  //各自指定
const MAX_KEY_SIZE = 1000;
//除外するバケット名を記述
const excludeTables = [
  "hoge",
  "fuga"
];

//Objectを削除するPromiseオブジェクト
var deleteObject = function(bucketName, key) {
  return new Promise((resolve, reject) => {
    s3.deleteObject({  //Objectを削除
      Bucket: bucketName,
      Key: key
    })
    .promise()
    .then((data) => {
      console.log("  [Key]" + key + " DELETED");
      resolve();
    })
    .catch((err) => {
      reject("  [Error]" + key + " NOT DELETED ¥n" + err);
    });
  });
}

s3.listBuckets({})  //Bucketの一覧を取得
.promise()
.then((data) => {
  let buckets = data.Buckets;
  buckets.filter((bucket) => {
    return (bucket.Name && excludeTables.indexOf(bucket.Name) == -1);
  })
  .map((bucket) => {
    s3.listObjects({Bucket: bucket.Name, MaxKeys: MAX_KEY_SIZE})  //Objectの一覧を取得
    .promise()
    .then((object) => {
      Promise.all(object.Contents.map((content) => {
        return deleteObject(object.Name, content.Key);
      }))
      .then(() => {
        s3.deleteBucket({  //Bucketの削除
          Bucket: object.Name
        })
        .promise()
        .then(() => {
          console.log("[Bucket] " + object.Name + "  DELETED");
        });
      })
      .catch((err) => {
        console.log(err);
      });
    })
    .catch((err) => {
      console.log(err);
    });
  })
})
.catch((err)=>{
  console.log(err);
});

実行方法

npm installしてからスクリプトをnode.jsで実行します。

$ npm install
$ node s3-delete.js

まとめ

Dynamoのテーブルの削除と同様に簡単にできるのかと思いきや、バケット自体を空にしなくてはいけないっていうのがちょっと面倒でした。これで、今後のインターン運営が楽になりそうです。