LoginSignup
0
0

Serverless FrameworkでS3 Triggerをローカルでエミュレートする

Posted at

TL;DR

  • serverless-s3-localというプラグインを使おう
  • cliしか使えないのでGUIで操作できないのがちょっとキツイかも
  • Serverlessの公式ドキュメントは優しい英語で書かれているので読みやすくて助かる

動機

Serverless Frameworkを触っていたらS3 Triggerをローカルで実行したくなりました。
今まではローカルではhttp リクエストを投げることで挙動を確認していましたが、
Handlerに投げられるEventがhttpリクエストとは異なるのでs3 trigger用のmockを用意して
動作確認していましたが、なんか。。。うーん。。。って感じだったので重い腰をあげて調べてみました。

前提事項

  • serverless frameworkのインストール
  • aws-cliのインストール

実装

sls create & プラグインインストール

自分はaws-nodejs-typescriptを使います。
動作確認してはいませんが、他のランタイムを選択してもできると思います。

sls create --template aws-nodejs-typescript --path ./sample --name sample 

あとは、ローカルでAPI Gatewayをエミュレートするserverless-offlineとS3をローカルでエミュレートするserverless-s3-localをインストールします。

npm install -D serverless-offline
npm install -D serverless-s3-local

serverless.tsにリソース情報を変更

serverless.tsにpluginを追記しましょう

serverless.ts
const serverlessConfiguration: AWS = {
  service: 'sample',
  frameworkVersion: '3',
  plugins: ['serverless-esbuild', 'serverless-offline', 'serverless-s3-local'],
  provider: {
    name: 'aws',
    runtime: 'nodejs18.x',
    apiGateway: {
      minimumCompressionSize: 1024,
      shouldStartNameWithService: true,
    },
    environment: {
      AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
      NODE_OPTIONS: '--enable-source-maps --stack-trace-limit=1000',

    ...

あとは、serverless-s3-localの設定をcustomに記述します。
記述する内容は以下の公式ドキュメントを参照してください。
https://www.serverless.com/plugins/serverless-s3-local

serverless.ts
custom: {
    esbuild: {
      ...
    },
    s3: {
      host: 'localhost',
      port: 4569,
      directory: './s3'
    }
  },

serverless.tsのfunctionsにLambdaの情報を記述します。
今回はめちゃくちゃ単純にconsoleにeventをconsoleに出力するだけの簡単なものにします。

serverless.ts
...
  functions: {
    trigger: {
      name: 'trigger',
      handler: `${handlerPath(__dirname)}/trigger.trigger`,
      events: [
        {
          s3: {
            bucket: 'trigger_bucket',
            event: 's3:*'
          }   
        }
      ]
    },
  }
...

resourcesにS3の情報を書きます。

serverless.ts
resources: {
    Resources: {
      triggerBucket: {
        Type: 'AWS::S3::BUCKET',
        Properties: {
          BucketName: 'trigger',
        }
      },
    }
}

これでリソースの構成の記述がおわりました。
trigger handlerにLambdaの挙動を記述しておきましょう。

trigger.ts
export const trigger: Handler = async(event) => {
  console.log(event)
  formatResponse({}, 200)
}

最後にpackage.jsonのscriptsにコマンド込めましょう。

package.json
 "dev": "IS_OFFLINE=true sls offline start --reloadHandler"
npm run dev

これでs3とAPI Gatewayをローカルで起動できました。

aws-cliを使う際のprofileの設定

ここから動作確認でs3にオブジェクトをaws-cliを使って格納します。
その際に認証情報が必要なのでそれをローカルに設定します。

先ほどのcustomに明示的に設定していなければデフォルトではアクセスキー、シークレットキーどちらもS3RVERです。
このキーを使ってaws-cliを実行できるようにprofileに設定しましょう。

~/.aws/config
[profile s3local]
aws_access_key_id = S3RVER
aws_secret_access_key = S3RVER

これでaws-cliを使う際に--profile s3localとオプションを指定することでこちらの認証情報をつかって実行できます。

動作確認

trigger bucketにオブジェクトを作成してコンソールにeventが出力されるか確認しましょう。
適当なファイルを作成しましょう。

sample.json
{
    "foo": "bar"
}

これをbucketにcpコマンドを使って格納します。

aws s3 cp sample.json s3://trigger/sample.json --endpoint-url http://localhost:4569 --profile s3local

このコマンドを実行するとnpm run devしたコンソールに以下のようなS3 Triggerのeventが出力できているはずです。

[
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "us-east-1",
      "eventTime": "",
      "eventName": "ObjectCreated:Put",
      "userIdentity": { "principalId": "" },
      "requestParameters": { "sourceIPAddress": "::1" },
      "responseElements": {
        "x-amz-request-id": "",
        "x-amz-id-2": ""
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigId",
        "bucket": {
          "name": "sample",
          "ownerIdentity": { "principalId": "" },
          "arn": "arn:aws:s3: : :sample"
        },
        "object": {
          "key": "sample.json",
          "sequencer": "",
          "size": 15,
          "eTag": ""
        }
      }
    }
  ]

eventが出力できました。
エラーが出る場合はs3バケットがちゃんと作成されているかなどを確認してください。

最後に

  • コマンドライン操作しかできなくて大変だなぁ
  • minioのほうがGUIで操作できて楽だけどtriggerできないからなぁ
  • 使い分けが大事そうだなぁ
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0