AWS Lambdaの開発をローカルで行う

記事タイトルとURLをコピーする

法人営業課でOJT中の鎌田です。近頃アイスブレイクの鉄板は「身近にあるけど気にしたことがないもの」だとおもっています。例えば、弊社は毎年社員旅行に行っていますが、そもそものきっかけはなんだったのだろう、とか。

さて、AWSでよく行う作業のうち面倒なことの一つに、Lambdaの動作確認があります。例えば、S3に操作が行われたことをトリガーにLambdaを起動すると、どのバケットに対して、どんな動作がいつ行われたか、といったイベント情報がLambdaに渡されます。このイベント情報を前提としたアプリケーションの動作確認時には、以下の一連の作業を繰り返し行うこととなります。

1.コードを修正する
2.ライブラリとソースコードをzipファイルにまとめる
3.zipファイルをアップロードする
4.Lambda関数のテストを定義して実行する or 実際にトリガーとなる操作を行う

今回はソースコードに対してイベント情報が渡される動作をローカルで再現することで、この1~4の手順を省力化しました。下記がその動作を再現するコードになります。

コード

var event = {
  "Records": [
    {
      "awsRegion": "ap-northeast-1",
      "sequenceNumber": "196800000000000000000374",
      "partitionKey": "khohohoihoihohoihoihohohohohoh",
      "eventSource": "aws:s3",
         "s3":{
            "bucket":{
               "name":"chicken-bucket",
               "arn":"bucket-ARN"
            },
            "object":{
               "key":"tekito.jpg"
            }
    }
  }
  ]
};

var context = {
    invokeid: 'invokeid',
    done: function(err,message){
        return;
    }
};


var lambda = require("./index");
lambda.handler(event,context);

上記コードはS3にファイルのputが行われたことをトリガーとしてLambdaファンクションが呼び出され、ソースコードにイベント情報を渡す動作を再現しています。
var eventの部分で、どの種類のイベントか、どんな情報が渡されたかの定義をしています。

これを「driver.js」として保存します。このdriver.jsと同一ディレクトリにテスト対象となるnode.jsのコードを置き(今回はindex.js)、driver.jsを実行すると動作確認ができます。実行方法は、コマンドラインでnode driver.jsと入力してください。
※node.jsをインストールしている必要があるのでご注意ください。

ちなみに今回テスト対象としたコードは以下です。おためしになる際には、「index.js」と名前をつけてdriver.jsと同じディレクトリに保存してください。これを実行するとtekito.jpgという名前のテキストファイルが生成されます。テキトーですね。

const aws = require('aws-sdk');
const s3 = new aws.S3();
const exec = require('child_process').exec;
const fs = require('fs');


exports.handler = function(event, context) {
//downloadしてファイルを書き込む
  var bucket = event.Records[0].s3.bucket.name;
  var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
  var params = {
    Bucket: bucket,
    Key: key,
  };

    s3.getObject(params, (err, data) => {
      if (err) {
          console.log(err);
          const message = `Error getting object ${key} rom bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
          console.log(message);
          callback(message);
        } else {
      fs.writeFile('/tmp/' + key, key, function (err) {
      if (err) {
      console.log('error occured when writing file:' +err);
      }
        }
    );
}});

上記コードは基本的にはAWS公式のコードを引用しています。「export.handler」がdriver.jsによって呼び出される部分となります。

event以下は配列や辞書がネストしていて、例えばバケット名を取得するためには var bucket = event.Records[0].s3.bucket.name; と書きます。AWSのドキュメントにS3イベント通知の構造が載っていますので是非ご参照ください。
http://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/notification-content-structure.html

s3.getObjectにてdriver.jsが渡してきたパラメーターを読み込んでいます。このコードではもしも正常にダウンロードができなかった場合、渡されたkey名でテキストファイルを作成し保存します。

まとめ

今回はS3のイベント通知をローカルで再現しました。kinesisなど他のサービスに置き換えて利用することも可能です。都度デプロイを行い、実際にイベントを起こす、という動作確認作業を行っていた場合は、これを使うととても楽ができるようになります。ぜひおためしください。

参考にした記事: http://qiita.com/imaifactory/items/092e32b4fc0f69a94061