OpenAPI Generator でクライアントライブラリを作成してみる

# はじめに
Web APIサービスに対応したクライアントライブラリ開発を手助けしてくれる **[OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator)** について調べてみた。

※ ここでは言語対象を「Python」として記載する。

# Swagger CodeGenとの違い
同じくOpenAPI Specificationを使ってコード生成するツールとして [Swagger CodeGen](https://github.com/swagger-api/swagger-codegen) もある。

Swagger CodeGenはSMARTBEAR社によってサポートされているプロジェクト。
OpenAPI Generatorは、2018年にSwagger CodeGenからフォークして始まった開発コミュニティ主体のプロジェクト。

誕生経緯は以下で語られている。
https://speakerdeck.com/akihito_nakano/gunmaweb34

Swagger CodeGenは現在もメンテナンスはされているが、OpenAPI Generatorの方が活発なようなのでそちらを使うほうが良さそう。

# OpenAPI Generatorでライブラリ生成しているサービス・企業
活用例については別記事でまとめた。

https://qiita.com/mmclsntr/items/edaea22802cdf2ffcc69

----

# 実行してみる
使い方についてはUsageページが参考になった。

https://openapi-generator.tech/docs/usage/#generate

上記のページでも紹介されている、サンプルの「[petstore.yaml](https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml)」があるため、これを使って試してみた。

## 基本的な使い方
コマンドはいくつか実行方法があるが、今回はdockerを使った方法とする。

基本型はこの形。

```sh
docker run --rm \
  -v ${PWD}:/local openapitools/openapi-generator-cli generate \
  -i /local/petstore.yaml \
  -g python \
  -o /local/petstore/python
```
このように `-i` でSpec fileを指定、`-g` で言語を指定、`-o` で生成されるファイルの出力先を指定する。

これを実行するとSpec fileに合わせたクライアントライブラリが作成される。

## 生成されるファイル群

**Python** の場合、このようなファイルが生成される。

```text
.
├── .gitignore
├── .gitlab-ci.yml
├── .openapi-generator/
├── .openapi-generator-ignore
├── .travis.yml
├── README.md
├── docs/
│   ├── apis/
│   └── models/
├── git_push.sh
├── openapi_client/
│   ├── __init__.py
│   ├── api_client.py
│   ├── apis/
│   ├── configuration.py
│   ├── exceptions.py
│   ├── model/
│   ├── models/
│   ├── paths/
│   ├── rest.py
│   └── schemas.py
├── requirements.txt
├── setup.cfg
├── setup.py
├── test/
│   ├── __init__.py
│   ├── test_models/
│   └── test_paths/
├── test-requirements.txt
└── tox.ini
```

Gitリポジトリとして `README.md` も含めてまるっと生成される。

`openapi_client/` がライブラリの本体で、 そのほか `test/` にはテストコードが、`docs/` にはライブラリのドキュメントが生成され、クライアントに必要な基本的なファイルが網羅されている。


## 生成時の設定パラメータ
パラメータは大きく分けて2種類ある。

- [Global Properties](https://openapi-generator.tech/docs/globals)
    - 共通パラメータ。
- [Configuration Options](https://openapi-generator.tech/docs/configuration)
    - 各言語ごと、Client/Serverごとに設けられているパラメータ。
    - 参照: https://openapi-generator.tech/docs/generators/
    - Config fileで管理可能。

最低限指定しておきたいと思うパラメータはこのあたり。

- packageName
    - デフォルトは `openapi_client` となっているため、任意のものに変更。

このように直接コマンドラインに指定する形、

```sh
docker run --rm \
  -v ${PWD}:/local openapitools/openapi-generator-cli generate \
  -i /local/petstore.yaml \
  -g python \
  -o /local/petstore/python \
  --package-name petstore
```

または config ファイルで管理することも可能。

```yaml:config.yaml
packageName: petstore
```

```sh
docker run --rm \
  -v ${PWD}:/local openapitools/openapi-generator-cli generate \
  -i /local/petstore.yaml \
  -g python \
  -o /local/petstore/python \
  -c config.yaml
```


## 生成されたライブラリを使用する

まずは、Python環境にインストールする。

```sh
pip install -e ${PWD}/petstore/python/
```

生成されたREADME.mdにExampleが載っているため、それを参考に使ってみた。

(載っているサンプルをそのまま使うといくつかエラーが出たので、適宜修正。)

以下、Petを追加する場合のサンプル。

```python
import petstore
from petstore.apis.tags import pet_api
from petstore.model.pet import Pet, Category, Tag

configuration = petstore.Configuration(
    host = "https://petstore.swagger.io/v2"
)

with petstore.ApiClient(configuration) as api_client:
    # Create an instance of the API class
    api_instance = pet_api.PetApi(api_client)
    pet = Pet(
        id=0,
        category=Category(
            id=1,
            name="test",
        ),
        name="doggie",
        photoUrls=[
            "photo_urls_example"
        ],
        tags=[
            Tag(
                id=1,
                name="name_example",
            )
        ],
        status="available",
    )

    try:
        api_response = api_instance.add_pet(pet, accept_content_types=('application/json', ), content_type='application/json')
        print(api_response)
    except petstore.ApiException as e:
        print("Exception when calling PetApi->add_pet: %s\n" % e)

```

----

# 所感
## 個人的ポイント
- Access Tokenを指定すればAuthorizationヘッダーに格納されてリクエストされる。ただし、そのAccess Tokenを発行するためのコード (OAuthなど) は内包されていないため別途用意が必要。
    - 認証方法はサービスによって異なるところなので...
- SpecファイルのValidationも行われる。
    - Skipしたい場合は `--skip-validate-spec` optionをつける。

## 良さそうな点
- さまざまな言語のクライアントを一気に生成できるところ。
    - 生成自体はかなりすぐ完了するため、お手軽。
- Docsも含め網羅的に生成されるため、生成後すぐに展開可能な状態。

## 気をつけなさそうな点
- 良くも悪くもほぼ全てのコードがOpenAPI Generatorに依存するため、issueへの対処をどうするか。
- 生成されたものを使ってちゃんと期待する動作を行えるのかは結局確認するべき。
    - テストコードも生成されるためうまく使ってテストしたい。
- どこまでのカスタマイズ性があるのか。そして、どの程度までのカスタマイズまでならシンプルな運用にとどめられるのか。