From 9e3f47b1497649f808ec25943b3b2d9ed318ef78 Mon Sep 17 00:00:00 2001 From: w-mj Date: Sat, 1 Apr 2023 21:30:52 +0800 Subject: [PATCH] API Document --- API.md | 186 +++++++++++++++++++++++++++++ src/controller/image_controller.go | 14 ++- src/model/data_model.go | 12 +- src/model/project_model.go | 26 ++-- 4 files changed, 222 insertions(+), 16 deletions(-) create mode 100644 API.md diff --git a/API.md b/API.md new file mode 100644 index 0000000..9591c19 --- /dev/null +++ b/API.md @@ -0,0 +1,186 @@ +# API 文档 + +## 总体设计 + +### 基本HTTP请求 + +本系统后端API设计遵循RESTful规范,对于一般数据类型的增删改查使用同一URL下的POST、DELETE、PUT和GET方法进行访问。 +对于POST和PUT方法,待传输数据放在请求体中,以Json格式进行传输。DELETE和GET方法使用URL参数传递必要数据。POST为上传新数据,使用POST时数据中ID字段将被忽略。 + +后端返回数据也全部为Json格式,使用HTTP状态码标识请求状态。当状态码为200时可以认为该请求成功达到了预期的结果。若请求失败,则状态码不为200,并且返回数据中包含`msg` +字段对发生的错误进行了简要说明。 + +一次失败的请求返回数据如下所示,其状态码为401(StatusUnauthorized)。 + +```json +{ + "ok": false, + "msg": "username error" +} +``` + +一般数据类型包含`ID`字段,类型为整数。DELETE方法可用此字段表示将要删除的对象。删除一个镜像的请求如下命令所示。 + +```bash +curl -X DELETE https://ms.educg.net/admin/image?ID=1 +``` + +### 资源查询请求 + +对单个资源查询的方式与删除类似,可使用该数据结构中的某些字段对数据进行查询,返回结果为Json格式。 + +同时对该类型的多个资源进行查询时,URL一般为该资源类型的复数形式,如镜像的查询URL为`image` +,那么同时获得多个镜像的查询的URL为`images`。特殊情况另行说明。 +对多个数据进行查询时,URL中除了必要的过滤条件外,还可包含分页参数`page`和`pageSize`,均为整数类型。返回结果中`data` +字段为查询结果数据,`page`、`pageCount`和`pageSize`用于控制分页。 + +```json +{ + "page": 1, + "pageCount": 100, + "pageSize": 2, + "data": [ + { + "ID": 2, + "Other fields": "Other Values" + }, + { + "ID": 3 + } + ] +} + +``` + +### 数据结构 +数据结构使用Golang语言格式进行定义,其中`gorm.Model`为公用字段,定义如下: +```go +type Model struct { + ID uint `gorm:"primarykey"` + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt DeletedAt `gorm:"index"` +} +``` + +数据结构中包含的Comment字段为该数据的简单描述,Doc字段为该数据的详细文档,文档应支持Markdown格式保存和渲染。 + +## 镜像管理 + +数据结构: + +```go +type ImageModel struct { + gorm.Model + Name string + Image string + Comment string + Command string + Env string + Port string + UserName string + IsPublished bool + Doc string +} +``` +CURD: ++ POST:/image ++ PUT: /image ++ DELETE: /image?ID=1 ++ GET /images?UserName=cg_wmj # 查询某用户的镜像 ++ GET /images?IsPublish=1 # 查询所有公开镜像 + +## 数据集管理 (尚未实现) + +训练数据,数据结构: +```go +type DataModel struct { + gorm.Model + Type string + Name string + Comment string + Doc string + UserName string + Password string + AccessInfo string + IsPublished bool +} +``` +其中`Type`字段为数据集的类型,表示该数据集的访问方式,目前仅支持`Type=="dir"`访问目录格式数据,后续可能支持mysql等数据库。 +本系统中,对本地文件的访问使用Webdav协议。 +`AccessInfo`字段为该数据集的访问方式,在`Type=="dir"`时为该目录的路径。 +例如某数据集对象中,`AccessInfo=='/some/data/dir/'`,同时本系统后端地址为`https://ms.educg.net/admin/ `,那么通过WebDav协议访问`https://ms.educg.net/files/some/data/dir/ `即可访问该目录。 + + +CURD: ++ POST:/data ++ PUT: /data ++ DELETE: /data?ID=1 ++ GET /data?UserName=cg_wmj ++ GET /data?IsPublish=1 + +## 项目管理 (尚未实现) + +数据结构 +```go +type ProjectModel struct { + gorm.Model + ProjectName string + UserName string + GroupName string + Type string + Comment string + Doc string + IsPublic bool + + ImageID int + Image ImageModel + TrainData []*DataModel `gorm:"many2many:projects_data"` + + + UserPath string // 用户目录挂载位置 + CodePath string // 代码目录挂载位置 + ModelPath string // 模型目录挂载位置 + + Running bool `gorm:"-:all"` +} +``` + +其中`Type`字段为项目的类型,可选值为`jupyter`、`jupyterlab`、`jupyternotebook`、`novnc`、`vscode`、`http`。 + +在创建或更新项目时,`TrainData`字段应该为DataModel结构的列表,其中每一个DataModel仅有`ID`即可。 + +CURD: ++ POST:/project ++ PUT: /project ++ DELETE: /project?ID=1 ++ GET /projects?UserName=cg_wmj ++ GET /projects?IsPublish=1 + +## 运行项目 (尚未实现) + +数据结构 +```go +type RunningProject struct { + Project *ProjectModel + StartTime *time.Time + UserName string + Nodes int + Cpus int + Memory int + Gpus int + GpuMemory int + URL string + ControlURL string +} +``` + +运行一个项目,前端发送POST请求时URL可留空,若该项目成功启动,则POST的返回内容中将包含正确的URL。 +通过此URL即可访问项目服务。ControlURL为容器服务客户端连接地址,可通过本地客户端提供更多功能。 + +此数据结构中没有ID字段,删除时使用其对应的ProjectModel的ID。 + +CURD: ++ POST:/running_project ++ DELETE: /running_project?ProjectID=1 ++ GET /running_projects?UserName=cg_wmj diff --git a/src/controller/image_controller.go b/src/controller/image_controller.go index c5b868b..60e0b08 100644 --- a/src/controller/image_controller.go +++ b/src/controller/image_controller.go @@ -6,6 +6,7 @@ import ( "k8s-manager/src/model" utils "k8s-manager/src/utils" "net/http" + "strconv" ) func AddImage(c *gin.Context) { @@ -20,18 +21,23 @@ func AddImage(c *gin.Context) { } func DeleteImage(c *gin.Context) { - image := &model.ImageModel{} - if utils.GinErrorCheck(c, c.BindJSON(image)) { + id := c.Query("ID") + if id == "" { + utils.GinError(c, http.StatusBadRequest, "no id") return } username := c.MustGet("username").(string) - oldImage := &model.ImageModel{Model: gorm.Model{ID: image.ID}} + idi, err := strconv.Atoi(id) + if utils.GinErrorCheck(c, err) { + return + } + oldImage := &model.ImageModel{Model: gorm.Model{ID: uint(idi)}} oldImage.Fill() if oldImage.UserName != username { utils.GinError(c, http.StatusUnauthorized, "username error") return } - image.Delete() + oldImage.Delete() } func UpdateImage(c *gin.Context) { diff --git a/src/model/data_model.go b/src/model/data_model.go index 1a58597..57276f9 100644 --- a/src/model/data_model.go +++ b/src/model/data_model.go @@ -7,10 +7,14 @@ import ( type DataModel struct { gorm.Model - Type string - Name string - Comment string - AccessInfo string + Type string + Name string + Comment string + Doc string + UserName string + Password string + IsPublished bool + AccessInfo string } func (*DataModel) TableName() string { diff --git a/src/model/project_model.go b/src/model/project_model.go index c06efed..5912ae8 100644 --- a/src/model/project_model.go +++ b/src/model/project_model.go @@ -12,10 +12,18 @@ type ProjectModel struct { GroupName string Type string Comment string + Doc string + IsPublic bool ImageID int Image ImageModel TrainData []*DataModel `gorm:"many2many:projects_data"` + + UserPath string + CodePath string + ModelPath string + + Running bool `gorm:"-:all"` } func (*ProjectModel) TableName() string { @@ -23,12 +31,14 @@ func (*ProjectModel) TableName() string { } type RunningProject struct { - Project *ProjectModel - StartTime *time.Time - UserName string - Nodes int - Cpus int - Memory int - Gpus int - GpuMemory int + Project *ProjectModel + StartTime *time.Time + UserName string + Nodes int + Cpus int + Memory int + Gpus int + GpuMemory int + URL string + ControlURL string }