Open6
goの練習がてらopenAPIドキュメントからコードを自動生成してアプリを作ってみる
アプリの内容としてはシンプルにメモのCRUDが出来るアプリ。
DBには使い慣れたmysql、マイグレーションツールはsql-migrateを使ってみる。
CRUDのapiをざっくりopenapiドキュメントに起こす
openapi: 3.0.3
info:
title: memo-go
version: 1.0.0
description: メモのCRUD用API
servers:
- url: 'http://localhost:8080'
description: develop
paths:
/memos:
get:
description: dbに登録されたメモのタイトル一覧を取得する
responses:
'200':
description: Ok
content:
application/json:
schema:
type: array
description: メモのタイトル一覧
items:
type: object
properties:
id:
type: integer
description: メモのid
title:
type: string
description: メモのタイトル
required:
- id
- title
'500':
$ref: '#/components/responses/500InternalServerError'
operationId: getMemos
summary: メモの一覧取得
post:
summary: メモの作成
operationId: postMemos
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
id:
type: integer
description: メモのid
required:
- id
'400':
description: Bad Request
content:
application/json:
schema:
type: object
properties:
message:
type: string
required:
- message
'500':
$ref: '#/components/responses/500InternalServerError'
description: 送られてきた情報でメモを作成する
requestBody:
content:
application/json:
schema:
type: object
properties:
title:
type: string
minLength: 1
maxLength: 255
description: メモのタイトル
content:
type: string
minLength: 1
maxLength: 21844
description: メモの中身
required:
- title
- content
description: 作成するメモの情報
'/memo/{id}':
get:
summary: メモの詳細
operationId: getMemo
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
id:
type: integer
description: メモのid
title:
type: string
description: メモのタイトル
content:
type: string
description: メモの中身
required:
- id
- title
- content
'404':
$ref: '#/components/responses/404NotFound'
'500':
$ref: '#/components/responses/500InternalServerError'
description: 対象idのメモの詳細を取得する
parameters: []
post:
summary: メモの更新
operationId: postMemo
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: 更新成功メッセージ
required:
- message
'404':
$ref: '#/components/responses/404NotFound'
'500':
$ref: '#/components/responses/500InternalServerError'
description: 送られてきた情報で対象idのメモを更新する
parameters:
- schema:
type: integer
minimum: 1
name: id
in: path
required: true
description: メモのid
delete:
summary: メモの削除
operationId: deleteMemo
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: 削除成功メッセージ
required:
- message
'404':
$ref: '#/components/responses/404NotFound'
'500':
$ref: '#/components/responses/500InternalServerError'
description: 対象idのメモを削除する
components:
responses:
500InternalServerError:
description: Internal Server Error
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: エラーメッセージ
required:
- message
404NotFound:
description: Not Found
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: エラーメッセージ
required:
- message
openapi-generatorでgoのサーバー側のスケルトンを自動生成
> docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
-i /local/openapi.yml \
-g go-server \
-o /local
生成されたファイル達
> tree
.
├── Dockerfile
├── api
│ └── openapi.yaml
├── go
│ ├── api.go
│ ├── api_default.go
│ ├── api_default_service.go
│ ├── error.go
│ ├── helpers.go
│ ├── impl.go
│ ├── logger.go
│ ├── model_inline_object.go
│ ├── model_inline_response_200.go
│ ├── model_inline_response_200_1.go
│ ├── model_inline_response_200_2.go
│ ├── model_inline_response_200_3.go
│ ├── model_inline_response_200_4.go
│ ├── model_inline_response_400.go
│ ├── model_inline_response_500.go
│ └── routers.go
├── go.mod
├── go.sum
├── main.go
└── openapi.yml
docker環境の構築
docker-compose.yml
services:
app:
build:
context: .
dockerfile: ./docker/app/Dockerfile
volumes:
- type: bind
source: ./
target: /go/src/app
ports:
- "8080:8080"
depends_on:
- db
tty: true
db:
image: mysql/mysql-server:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_ROOT_HOST: '%'
MYSQL_DATABASE: dev
MYSQL_USER: dev
MYSQL_PASSWORD: dev
TZ: "Asia/Tokyo"
volumes:
- type: bind
source: ./docker/db/my.cnf
target: /etc/mysql/conf.d/my.cnf
- type: volume
source: db_data
target: /var/lib/mysql
ports:
- 13306:3306
swagger-editor:
image: swaggerapi/swagger-editor
ports:
- "8001:8080"
swagger-ui:
image: swaggerapi/swagger-ui
ports:
- "8002:8080"
volumes:
- type: bind
source: ./openapi.yml
target: /openapi.yml
environment:
SWAGGER_JSON: /openapi.yml
volumes:
db_data:
driver: local
Dockerfile
FROM golang:1.17.2-alpine
WORKDIR /go/src/app
RUN apk update && apk add git
COPY go.mod go.sum ./
RUN go mod tidy
EXPOSE 8080
CMD ["go", "run", "main.go"]
my.cnf
[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_ja_0900_as_cs
default_authentication_plugin = mysql_native_password
default-time-zone = SYSTEM
log_timestamps = SYSTEM
slow_query_log_file = /tmp/mysqld.slow.log
slow_query_log = 1
long_query_time = 2
[mysql]
default-character-set = utf8mb4
マイグレーション
sql-migrateをinstallするようにDockerfileを編集
Dockerfile
FROM golang:1.17.2-alpine
WORKDIR /go/src/app
RUN apk update && apk add git
COPY go.mod go.sum ./
ARG CGO_ENABLED=0
RUN go mod tidy && \
go install github.com/rubenv/sql-migrate/...@latest
EXPOSE 8080
CMD ["go", "run", "main.go"]
sql-migrateの設定ファイル
dbconfig.yml
development:
dialect: mysql
datasource: dev:dev@tcp(db:3306)/dev?parseTime=true
dir: migrations
コンテナの中で以下のコマンドを実行し、マイグレーションファイルを生成。
/go/src/app/migrate # sql-migrate new create_memo
作成したマイグレーションファイル
20211017103235-create_memo.sql
-- +migrate Up
CREATE TABLE IF NOT EXISTS memo (
id int(15) AUTO_INCREMENT,
title varchar(255),
content text,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id));
-- +migrate Down
DROP TABLE IF EXISTS memo;
マイグレーションの実行
/go/src/app/migrate # sql-migrate up
Applied 1 migration
/go/src/app/migrate # sql-migrate status
+--------------------------------+-------------------------------+
| MIGRATION | APPLIED |
+--------------------------------+-------------------------------+
| 20211017103235-create_memo.sql | 2021-10-17 10:59:48 +0000 UTC |
+--------------------------------+-------------------------------+
TODO
- とりあえず直でdbにデータを入れる
- sqlクライアントを使ってdbと接続し、参照APIを動くようにする
- テスト書く
- 他のAPIも動くようにする