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を追記しましょう
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
custom: {
esbuild: {
...
},
s3: {
host: 'localhost',
port: 4569,
directory: './s3'
}
},
serverless.ts
のfunctionsにLambdaの情報を記述します。
今回はめちゃくちゃ単純にconsoleにeventをconsoleに出力するだけの簡単なものにします。
...
functions: {
trigger: {
name: 'trigger',
handler: `${handlerPath(__dirname)}/trigger.trigger`,
events: [
{
s3: {
bucket: 'trigger_bucket',
event: 's3:*'
}
}
]
},
}
...
resourcesにS3の情報を書きます。
resources: {
Resources: {
triggerBucket: {
Type: 'AWS::S3::BUCKET',
Properties: {
BucketName: 'trigger',
}
},
}
}
これでリソースの構成の記述がおわりました。
trigger handlerにLambdaの挙動を記述しておきましょう。
export const trigger: Handler = async(event) => {
console.log(event)
formatResponse({}, 200)
}
最後にpackage.jsonのscriptsにコマンド込めましょう。
"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に設定しましょう。
[profile s3local]
aws_access_key_id = S3RVER
aws_secret_access_key = S3RVER
これでaws-cliを使う際に--profile s3local
とオプションを指定することでこちらの認証情報をつかって実行できます。
動作確認
trigger bucketにオブジェクトを作成してコンソールにeventが出力されるか確認しましょう。
適当なファイルを作成しましょう。
{
"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できないからなぁ
- 使い分けが大事そうだなぁ