Amazon S3にドキュメントを置いたらLambda経由でSlackに通知させてみた

  • 9
    いいね
  • 0
    コメント

やりたかったこと

S3にファイルをアップロードしたタイミングでSlackに通知する仕組みを作りました。
だいたい1時間くらいで実装できます。
実装後のイメージとして、まずはこんな感じにS3にファイルをアップロードします。
UploadToS3.jpg
するとSlackに通知されます。
UploadNotification.jpg

仕組み

通知の仕組みを図で表すこんな感じです。
S3toSlackOverview.jpg
AWSのサービス間は連携が優れています。この辺のサービスを作った結果の感想をマイクロサービス否定派が変節した経験に書いています。

Slack側設定

Slackの受信設定をincoming webhook integrationから設定します。
投稿するチャネルを選択して"Add Incoming WebHooks integration"を押します。
SlackWebhookSetting.jpg
そうすると、Webhook URLが発行されます。
SlackWebhookResult.jpg

AWS Lambda設定

AWS Lambda設定を簡単にスクリーンショットを貼っていきます。

1. Select blueprint

blueprintからs3-get-objectを選択します。ここはpythonでもよかったのですが、特にこだわりなく選んでいます。
S3toSlack.jpg

2. Configure triggers

S3のBucket名とEven type(Put)を選択。
S3toSlack_02.ConfigureTriggers.jpg

3. Configure function

あとはその他の属性を入力します。
S3toSlack_03.ConfigureFunction.jpg
S3toSlack_03.ConfigureFunction2.jpg

AWS Lambdaのコーディング

最後にコーディング。動けばいい程度の認識でコーディングしたので、正直、自信がありません(Node.jsはお遊び程度の知識しかないですし)。

S3toPostSlack.js
'use strict';
console.log('Loading function');

let aws = require('aws-sdk');
let s3 = new aws.S3({ apiVersion: '2006-03-01' });

var url        = require("url");
var http       = require('http');
var https      = require('https');
var webhookUrl = url.parse("https://hooks.slack.com/services/<path>");

var webhookOptions = {
  hostname: webhookUrl.hostname,
  path:     webhookUrl.path,
  port:     443,
  method:   "POST",
  headers: { "Content-Type": "application/json"  }
};

exports.handler = (event, context, callback) => {
    //console.log('Received event:', JSON.stringify(event, null, 2));

    // Get the object from the event and show its content type
    const bucket = event.Records[0].s3.bucket.name;
    const key    = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
    const size   = Math.floor(event.Records[0].s3.object.size / 1024);
    const params = {
        Bucket: bucket,
        Key: key
    };

    var filename = event.Records[0].s3.object.key;
    var payload = JSON.stringify({
        channel:    "#<channel name>",
        icon_emoji: ":paperclip:",
        username:   "S3 Backet:" + bucket,
        text:       key + "がアップロードされました:" + size + "MB"
      }); 

    console.log(payload);

    var req = https.request(webhookOptions, function(res) {
        res.setEncoding("utf8");
        res.on("data", function(chunk) {
          console.log(chunk);
          context.succeed();
        });
      }).on("error", function(e) {
        console.log("error: " + e.message);
      });
    req.write(payload);
    req.end();


    s3.getObject(params, (err, data) => {
        if (err) {
            console.log(err);
            const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
            console.log(message);
            callback(message);
        } else {
            console.log('CONTENT TYPE:', data.ContentType);
            callback(null, data.ContentType);
        }
    });
};

参考

以下の記事も併せて参考になるかと思います。