Serverless Frameworkで特定のタイミングで独自の処理を行うプラグインを作成する
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
背景
Serverless Frameworkでデプロイ等を行う際になにか独自の処理をはさみたいということがあると思います。この課題をServerless Frameworkのプラグインを作って解決します。
環境
下記の環境で試しています。
- Node.js: v14.16.1
- Serverless Framework: v2.50.0
サンプルプロジェクトの作成
まず、serverlessコマンドでexampleというサンプルのプロジェクトを作成します。
$ serverless What do you want to make? AWS - Node.js - Starter What do you want to call this project? example Downloading "aws-node" template... Project successfully created in example2 folder You are not logged in or you do not have a Serverless account. Do you want to login/register to Serverless Dashboard? No Do you want to deploy your project? No ... 略
プラグインの作成
次に単純に標準出力するだけのプラグインを作成してみます。
プラグイン用のディレクトリを作成してnpm initします。
$ mkdir plugin $ npm init
package.jsonではmainにindex.jsを指定するようにします。
{
"name": "example-plugin",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {},
"author": "",
"license": "ISC"
}
この段階でディレクトリ構成は下記のようになります。
.
├── example --> メインのコードが入ったディレクトリ
│ ├── handler.js
│ ├── package-lock.json
│ ├── package.json
│ └── serverless.yml
└── plugin --> プラグイン向けのディレクトリ
└── package.json
次にindex.jsにプラグインを実装します。
$ cd plugin $ touch index.js
まずはコンストラクタで標準出力するだけのコードを書いてみます。
// plugin/index.js
class ExamplePlugin {
constructor() {
console.log('this is a example-plugin');
};
}
module.exports = ExamplePlugin;
このプラグインをserverless.ymlのpluginsに指定します。通常はnpmパッケージの依存関係に追加した上でnpm installする必要がありますが、それ以外にもパス指定で追加することができます。
service: main frameworkVersion: '2' plugins: # プラグインは記述した順番に実行される # v1系だとこのパス指定する書き方はできない模様 # https://www.serverless.com/framework/docs/providers/aws/guide/plugins#service-local-plugin - ../plugin ... 略
指定方法についての詳細は下記のドキュメントを参照ください。
この状態で何かしらのコマンドを実行すると、コンストラクタに書いたthis is a example-pluginが標準出力されます。
$ sls deploy this is a example-plugin Serverless: Packaging service... Serverless: Excluding development dependencies...
デプロイ前に確認を促すようにしてみる
もう少し具体的なサンプルを作ってみます。具体的には下記のようなものを目指します。
- デプロイ前にデプロイする環境を表示する
- デプロイするかどうか
y/nで入力させる y以外を入力するとデプロイを中止する
これを実現するためにはhooksという機能を使用します。
Advanced Plugin Development - Extending The Serverless Core Lifecycle
標準入力にはNode.jsのreadlineを使います。
先程のplugin/index.jsのコードを下記のように書き換えます。
// https://nodejs.org/docs/latest-v14.x/api/readline.html
const readline = require('readline');
class ExamplePlugin {
constructor(serverless, options) {
this.options = options;
this.serverless = serverless;
// AWS向けなので注意
this.stage = this.serverless.providers.aws.getStage().toLowerCase();
// coreライフサイクルを拡張する
// https://www.serverless.com/blog/advanced-plugin-development-extending-the-core-lifecycle
this.hooks = {
'before:deploy:deploy': () => this.confirmDeploy(this.stage)
// serverless frameworkがserverless.ymlに記述したリソースのチェックなどを行う前に実行したい前ならinitialize
// 'before:deploy:initialize': () => this.confirmationDialog(this.stage)
}
};
// readlineで入力を待ち受けるためのPromiseを返す関数
confirmationDialog(stage) {
const readLine = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve, reject) =>
readLine.question(`${stage} : Do you wanna deploy? [y/n]`, (answer) => {
readLine.close();
if (answer.toLocaleLowerCase() !== 'y') {
// reject するとエラーで止まる
reject("Deploy aborted!");
}
resolve();
}));
}
}
module.exports = ExamplePlugin;
これでプラグインの変更が終わったのでデプロイ時にメッセージが表示されるかどうか確認します。y以外の値を入力するとデプロイが中断されるという挙動になっていることが確認できました。
$ sls deploy --stage dev
dev : Do you wanna deploy? [y/n]n
Exception -----------------------------------------------
'Deploy aborted!'
For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Issues: forum.serverless.com
... 略
まとめ
思っていたよりも簡単に独自の処理を挟むことができました。プラグインもpackage.jsonに依存関係を指定しなくてもserverless.ymlにパス指定すれば動作するなど、開発も容易だと感じました。
参考
Advanced Plugin Development - Extending The Serverless Core Lifecycle







