765DevOps

Thinking is the problem, Doing is the answer !

0%

Gin接入Swagger

在如今大环境下,人员越来越精简,手动 🐶 ,内部平台系统从需求->交付上线就一两个伙伴支撑,肿么还可能写Api文档呢……长期以往带来的问题,大家懂得都懂😂。

1、官方參考

swaggo连接: https://github.com/swaggo/gin-swagger

Swagger 相关语法参考请参考: Declarative Comments Format

2、gin框架引入

  • 接入后本地调试

① 生成Swagger文档

1
2
3
4
5
6
7
8
// 安装swaggo工具(go1.17+)
go install github.com/swaggo/swag/cmd/swag@latest

// 执行swagger之前使用fmt 格式化swagger注释
swag fmt

// 由于项目目录结构的原因,使用 -g 指定入口文件
swag init -g cmd/web/main.go --parseDependency

② 编译或调试键入参数

1
-tags swag

③ 访问

1
http://localhost:8089/swagger/index.html/swagger/index.html
  • routers包的router.go中申明变量
1
2
3
4
5
6
7
8
9
10
11
12
13
// 申明swagger handler,build中使用 -tags swag时,则加载swagger.go文件并init初始化该变量;若未使用则为 nil,不初始化swagger路由
var swagHandler gin.HandlerFunc

func InitRouter() *gin.Engine {
...
// Add swagger API support
// ① swagHandler != nil 编译侧,做限制,根据条件确定是否编译swagger包
// ② !configmgr.IsProd() 此处再次判断是为了避免避免线上直接交付制品导致swagger接口外泄)
if swagHandler != nil && !configmgr.IsProd() {
r.GET("/swagger/*any", swagHandler)
}
....
}
  • 在routers包中加入swagger.go

    使用条件编译的 build tag(即编译标签),当使用了 build -tags swag 则编译该文件,一是引入swagger生成的docs.go文件,二是初始化swagHandler变量,以便在路由初始化swagger文档。

**备注:不违背CICD制品交付原则(一次构建都出运行), -tags swag默认执行,通过在路由注册层面根据环境控制swaager 路由注册 **

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// +build swag

package routers

import (
"ztdemo/docs"

swaggerfiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)

func init() {
docs.SwaggerInfo.Title = "研发中台 API"
swagHandler = ginSwagger.WrapHandler(swaggerfiles.Handler)
}

3、CICD接入swagger

  • Dockerfile修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
FROM golang:1.19.3 as build

# 设置go 的相关环境变量
ENV GO111MODULE=on \
GOPROXY=https://goproxy.cn,direct \
GOPRIVATE=gitlab.2345.cn

RUN go install github.com/swaggo/swag/cmd/swag@latest

# 容器构建缓存共享方案,docker新增一层生成依赖的镜像,以go为例,优先处理go.mod go.sum,达到层级公用
# COPY go.mod go.sum 这里COPY的文件有变化的话,docker build会重新生成镜像
COPY go.mod go.sum /opt/build/

WORKDIR /opt/build

# 下载模块到本地缓存
RUN --mount=type=cache,target=/go/pkg/mod \
go mod download

# 传入LDFLAGS参数,指定应用相应版本、时间等信息
ARG LDFLAGS="-s -w"
# 使用build tags实现条件编译,线上不编译swagger
ARG BUILDTAGS="-tags swag"

# 注意加入.dockerignore,避免大量无用文件copy,如:.git、.idea、.vscode等
COPY . .

# 生成swagger文档,go build 根据tags确定是否进行条件编译
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build,id=jszx-yfzt_go-build-cache \
swag init -g cmd/web/main.go --parseDependency

# 指定OS等,并go build
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build,id=jszx-yfzt_go-build-cache \
GOOS=linux go build ${BUILDTAGS} -ldflags "${LDFLAGS}" -trimpath -o ./bin/yfzt ./cmd/web/main.go
  • 本地Swagger fmt(代码提交前swagger comment格式化)
1
2
3
4
5
// 执行swagger之前使用fmt 格式化swagger注释
swag fmt

// 由于项目目录结构的原因,使用 -g 指定入口文件
swag init -g cmd/web/main.go --parseDependency

4、Yapi集成配置

4.1 数据导入

位置:Yapi项目详情页 -> 数据管理Tab ,功能使用说明>>

4.2 Swagger自动同步

位置:Yapi项目详情页 -> 设置Tab -> Swagger自动同步Tab

5、接入demo示例

目前平台的K8s文件浏览器接口全部接入的Swagger,可以参考,示例

文件:controller/v2/k8shelp/kubefilebrowser/filebrowser/create.go

1
2
3
4
5
6
7
8
9
10
11
12
13
// CreateDir
// @Summary 查看实例-文件管理-创建目录
// @description 容器文件浏览器 - 创建目录
// @Tags K8s文件浏览器
// @Param envId query Query true "环境ID"
// @Param namespace query Query true "namespace"
// @Param pod query Query true "Pod名称"
// @Param container query Query true "容器名称"
// @Param path query Query true "路径"
// @Success 200 {object} handlers.JSONResult
// @Failure 500 {object} handlers.JSONResult
// @Router /api/v2/filebrowser/createdir [post]
func CreateDir(c *gin.Context) {...}