Swaggerで定義したAPIをServerless Frameworkにインポートする

serverless-import-swaggerの紹介」という記事が気になったので、すこし触ってみました。

Swaggerで定義した内容をServerless Frameworkへインポートできるということで、ドキュメント作成はSwaggerで実装はServerless Frameworkという人にはすごく便利なライブラリかなと思います。

事前準備

Swaggerのサンプルファイルを用意するのがめんどう手間だったので、配布元のテストに使われているものを借用することにします。

$ mkdir swagger-test && cd swagger-test
$ npm init -y
$ wget https://raw.githubusercontent.com/AKIRA-MIYAKE/serverless-import-swagger/master/test/serverless.common.yml
$ wget https://raw.githubusercontent.com/AKIRA-MIYAKE/serverless-import-swagger/master/test/swagger.yaml

ここまででディレクトリ構成はこうなっているはずです。

$ tree
.
├── package.json
├── serverless.common.yml
└── swagger.yaml

serverless-import-swaggerをインストールする

実行するためにもインストールしましょう。
今回は敢えてローカルインストールにしています。

$ npm install --save-dev serverless-import-swagger
$ ./node_modules/serverless-import-swagger/bin/sis --help

  Usage: sis [options]

  Import functions from swagger spec filet to serverless.yml

  Options:

    -h, --help                     output usage information
    -V, --version                  output the version number
    -i, --input <path>             Specify swagger file path. (defailt "./swagger.ya?ml")
    -c, --common <path>            Specify common config of serverless file path. (default "./serverless.common.ya?ml")
    -o, --out-dir <path>           Specify dist directory of services. (default "./")
    -f, --force                    If add this option, overwriten serverless.yml by generated definitinos.
    -A, --api-prefix <prefix>      Specify target prefix for swagger tags. (default "sls")
    -S, --service-prefix <prefix>  Specify prefix that added service name. (default none)
    -B, --base-path                If add this option, run in a mode of dividing a service by a api base path.
    -C, --cors                     If add this option, added cors setting to all http event.
    -O, --options-method           If add this option, added cors setting to get http event, and added OPTIONS method to api path that including other http method.

Swaggerの情報をServerless Frameworkにインポートする

以下のようなコマンドを実行することで、swagger.yamlのデータをインポートできます。

$ ./node_modules/serverless-import-swagger/bin/sis \
  -i ./swagger.yaml \
  -c ./serverless.common.yml \
  -o ./api

-iでインポートするファイルを、-cでServerless Frameworkの全般設定内容を、-oでインポートしたServerless Frameworkプロジェクトの出力先を指定できます。

上のコマンドを実行すると、以下のようになります。

$ ./node_modules/serverless-import-swagger/bin/sis -i ./swagger.yaml -c ./serverless.common.yml -o ./api
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/EXAMPLE_USER/swagger-test/api/authentication"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.10.2
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs"

Write serverless.yml of authentication complete.
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/EXAMPLE_USER/swagger-test/api/test"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.10.2
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs"

Write serverless.yml of test complete.
Import success.

元のswagger.yamlをみる限り、tagsで指定したグループ毎にServerless Frameworkのプロジェクトが作成される様子です。
今回借用したものでは、sls-authenticationsls-testの2種類のタグが設定されていました。そのため、serverless createが2回実行されています。

実行後のディレクトリ構成

importに成功すると、以下のようなディレクトリ構成となります。

$ tree -I node_modules
.
├── api
│   ├── authentication
│   │   ├── handler.js
│   │   └── serverless.yml
│   └── test
│       ├── handler.js
│       └── serverless.yml
├── package.json
├── serverless.common.yml
└── swagger.yaml

swagger.yamltagsで指定されたsls-XXXのXXXがそれぞれディレクトリ名として作成されるということでしょうか。

ちなみにインポート後のserverless.ymlは以下のようになっていました。

api/authenticationserverless.yml

service: authentication
provider:
  name: aws
  runtime: nodejs6.10
  stage: testing
  region: ap-northeast-1
functions:
  hello:
    handler: handler.hello
  postAuthenticationSignup:
    handler: handler.postAuthenticationSignup
    events:
      - http:
          path: /authentication/signup
          method: post
          integration: lambda-proxy
  postAuthenticationConfirmSignup:
    handler: handler.postAuthenticationConfirmSignup
    events:
      - http:
          path: /authentication/confirm-signup
          method: post
          integration: lambda-proxy
  postAuthenticationSigninEmail:
    handler: handler.postAuthenticationSigninEmail
    events:
      - http:
          path: /authentication/signin/email
          method: post
          integration: lambda-proxy
plugins:
  - serverless-webpack

swagger.yamlの更新

APIを追加・変更する場合ですが、 swagger.yamlを変更して再度実行することで反映される様子です。

$ ./node_modules/serverless-import-swagger/bin/sis -i ./swagger.yaml -c ./serverless.common.yml -o ./api
Write serverless.yml of test complete.
Write serverless.yml of authentication complete.
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/EXAMPLE_USER/swagger-test/api/example"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.10.2
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs"

Write serverless.yml of example complete.
Import success.

当たり前といえば当たり前ですが、serverless.ymlの反映のみで、Lambdaに使用するJS / Pythonファイルなどまで書き換えてくれるわけではないので、要注意です。

おわりに

「SwaggerでAPIの概要を定義 → serverless-import-swaggerでServerless Frameworkにインポート → Serverless Frameworkにて実装」というワークフローは個人的にはありかなと思います。

中の人から「SAM使えー」という声が聞こえてきそうな気もしますが、今の所Serverless Frameworkで頑張る方がメリットが大きいと感じていますので、しばらくはこのあたりの方法を試してみます。

Follow me!