diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 0000000..c2e4bf5 --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,70 @@ +name: Build + +on: + push: + tags: + - 'v*.*.*' + +jobs: + build-and-push: + name: Build And Push + runs-on: ubuntu-latest + needs: [] + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Get version + id: version + run: | + if [[ $GITHUB_REF == refs/tags/* ]]; then + CURRENT_VERSION=${GITHUB_REF#refs/tags/} + echo "Triggered by tag: $CURRENT_VERSION" + echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT + else + echo "Triggered by branch push, calculating new version..." + LATEST_TAG=$(git tag -l "v*.*.*" | sort -V | tail -n1) + + if [ -z "$LATEST_TAG" ]; then + # If no tag, start from v1.0.0 + NEW_VERSION="v1.0.0" + else + echo "Latest tag: $LATEST_TAG" + VERSION_PART=$(echo $LATEST_TAG | sed 's/v//') + MAJOR=$(echo $VERSION_PART | cut -d. -f1) + MINOR=$(echo $VERSION_PART | cut -d. -f2) + PATCH=$(echo $VERSION_PART | cut -d. -f3) + + PATCH=$((PATCH + 1)) + NEW_VERSION="v${MAJOR}.${MINOR}.${PATCH}" + fi + + echo "New version: $NEW_VERSION" + echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT + fi + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up buildx + id: buildx + uses: docker/setup-buildx-action@v2 + with: + version: latest + + - name: Log in to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Push to Docker Hub + uses: docker/build-push-action@v3 + with: + context: . + target: runtime + platforms: linux/amd64 + push: true + tags: ${{ secrets.DOCKERHUB_REPOSITORY }}/taskd:${{ steps.version.outputs.version }},${{ secrets.DOCKERHUB_REPOSITORY }}/taskd:latest diff --git a/Dockerfile b/Dockerfile index 56fe1f0..7d0efc3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,26 +4,19 @@ COPY . . RUN go env -w CGO_ENABLED=0 && \ go env -w GO111MODULE=on && \ - go env -w GOPROXY=https://goproxy.cn,https://mirrors.aliyun.com/goproxy/,direct + go env -w GOPROXY=https://goproxy.cn,https://mirrors.aliyun.com/goproxy,direct -# -#go env -w GOPROXY=http://mirrors.sangfor.org/nexus/repository/go-proxy-group -# +RUN go mod tidy +RUN go build -ldflags="-s -w" -o taskd *.go +RUN chmod 755 taskd -RUN go mod tidy && go build -o taskd *.go +FROM alpine:3.21 AS runtime -FROM centos:7.6.1810 #时区设置 ENV env prod ENV TZ Asia/Shanghai WORKDIR / -# RUN curl -O http://10.72.1.16:30574/tools/kubectl -# RUN chmod 777 kubectl -# RUN mv kubectl /usr/bin/ -# RUN curl -O http://10.72.1.16:30574/tools/jq -# RUN chmod 777 jq -# RUN mv jq /usr/bin/ -COPY --from=builder /app/taskd /usr/local/bin -RUN chmod 755 /usr/local/bin/taskd + +COPY --from=builder /app/taskd /usr/local/bin/taskd ENTRYPOINT ["/usr/local/bin/taskd"] diff --git a/controllers/controllers.go b/controllers/controllers.go index 53d955d..2be8591 100644 --- a/controllers/controllers.go +++ b/controllers/controllers.go @@ -21,7 +21,7 @@ type ResponseData struct { Code string `json:"code"` Message string `json:"message"` Success bool `json:"success"` - Data any `json:"data"` + Data any `json:"data,omitempty"` } /** @@ -29,12 +29,7 @@ type ResponseData struct { */ func respOK(c *gin.Context, data any) { utils.Debugf("request: %+v, response: %+v", c.Request.RequestURI, data) - c.JSON(http.StatusOK, ResponseData{ - Code: "0", - Message: "OK", - Success: true, - Data: data, - }) + c.JSON(http.StatusOK, data) } /** @@ -43,7 +38,7 @@ func respOK(c *gin.Context, data any) { func respError(c *gin.Context, code int, err error) { utils.Errorf("request: %+v, error: %s", c.Request.RequestURI, err.Error()) if httpErr, ok := err.(*utils.HttpError); ok { - c.JSON(code, ResponseData{ + c.JSON(httpErr.Code(), ResponseData{ Code: strconv.Itoa(httpErr.Code()), Message: httpErr.Error(), Success: false, diff --git a/dao/instance.go b/dao/instance.go index 22937e0..3ff2dde 100644 --- a/dao/instance.go +++ b/dao/instance.go @@ -12,6 +12,7 @@ import ( */ type TaskObjRec struct { UUID string `json:"uuid,omitempty"` // Task UUID + Parent string `json:"parent,omitempty"` // The batch specified by this ID Namespace string `json:"namespace,omitempty"` // Namespace Name string `json:"name,omitempty"` // Task name Project string `json:"project,omitempty"` // Project name diff --git a/docs/docs.go b/docs/docs.go index 8bc450a..45c76b0 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -11,7 +11,7 @@ const docTemplate = `{ "title": "{{.Title}}", "termsOfService": "http://www.sangfor.com.cn", "contact": { - "name": "张钊晋,郑柏春", + "name": "Zhaojin Zhang,Bochun Zheng", "url": "http://www.sangfor.com.cn" }, "license": { @@ -25,7 +25,7 @@ const docTemplate = `{ "paths": { "/v1/pools": { "get": { - "description": "列举任务池信息,比如资源用量,运行任务概况", + "description": "List task pool information including resource usage and running task overview", "consumes": [ "application/json" ], @@ -33,12 +33,12 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "列举任务池", + "summary": "List task pools", "responses": { "200": { - "description": "OK", + "description": "Queue information", "schema": { "type": "array", "items": { @@ -49,7 +49,7 @@ const docTemplate = `{ } }, "post": { - "description": "添加一个任务池", + "description": "Add a task pool", "consumes": [ "application/json" ], @@ -57,12 +57,12 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "添加一个任务池", + "summary": "Add a task pool", "parameters": [ { - "description": "任务池", + "description": "Task pool", "name": "pool", "in": "body", "required": true, @@ -73,7 +73,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Task pool result", "schema": { "$ref": "#/definitions/service.TaskPoolResult" } @@ -83,7 +83,7 @@ const docTemplate = `{ }, "/v1/pools/{name}": { "get": { - "description": "获取任务池详情", + "description": "Get task pool details", "consumes": [ "application/json" ], @@ -91,27 +91,27 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "获取任务池详情", + "summary": "Get task pool details", "parameters": [ { "type": "string", - "description": "任务池名", + "description": "Pool name", "name": "name", "in": "path", "required": true }, { "type": "boolean", - "description": "是否获取详情", + "description": "Get detailed info", "name": "verbose", "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "Pool information", "schema": { "$ref": "#/definitions/task.TaskPoolDetail" } @@ -119,7 +119,7 @@ const docTemplate = `{ } }, "put": { - "description": "更新任务池定义", + "description": "Update task pool definition", "consumes": [ "application/json" ], @@ -127,19 +127,19 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "更新任务池", + "summary": "Update task pool", "parameters": [ { "type": "string", - "description": "任务池ID", + "description": "Task pool ID", "name": "name", "in": "path", "required": true }, { - "description": "任务池", + "description": "Task pool", "name": "pools", "in": "body", "required": true, @@ -150,7 +150,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Update task pool", "schema": { "$ref": "#/definitions/service.TaskPoolResult" } @@ -158,7 +158,7 @@ const docTemplate = `{ } }, "delete": { - "description": "删除任务池,同时删除关联的PoolResource", + "description": "Delete task pool and associated PoolResource", "consumes": [ "application/json" ], @@ -166,13 +166,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "删除任务池", + "summary": "Delete task pool", "parameters": [ { "type": "string", - "description": "任务池名", + "description": "Pool name", "name": "name", "in": "path", "required": true @@ -180,54 +180,25 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Delete success message", "schema": { "type": "string" } }, "400": { - "description": "Bad Request", + "description": "Running tasks exist", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "404": { - "description": "Not Found", + "description": "Pool not found", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controllers.ResponseData" - } - } - } - } - }, - "/v1/reload": { - "post": { - "description": "重新加载任务池相关配置,适用于池节点变更,节点资源变更,池轮询策略变更", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "任务池" - ], - "summary": "重新加载任务池相关配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - }, - "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -237,7 +208,7 @@ const docTemplate = `{ }, "/v1/tasks": { "get": { - "description": "列举任务", + "description": "List tasks", "consumes": [ "application/json" ], @@ -245,67 +216,67 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "列举任务", + "summary": "List tasks", "parameters": [ { "type": "string", - "description": "任务名称", + "description": "Task name", "name": "name", "in": "query" }, { "type": "string", - "description": "命名空间", + "description": "Namespace", "name": "namespace", "in": "query" }, { "type": "string", - "description": "任务属主", + "description": "Task owner", "name": "owner", "in": "query" }, { "type": "integer", - "description": "页码", + "description": "Page number", "name": "page", "in": "query" }, { "type": "integer", - "description": "每页数量", + "description": "Items per page", "name": "pageSize", "in": "query" }, { "type": "string", - "description": "待运行资源池", + "description": "Target resource pool", "name": "pool", "in": "query" }, { "type": "string", - "description": "项目名称", + "description": "Project name", "name": "project", "in": "query" }, { "type": "string", - "description": "排序字段", + "description": "Sort field", "name": "sort", "in": "query" }, { "type": "string", - "description": "任务状态", + "description": "Task status", "name": "status", "in": "query" }, { "type": "string", - "description": "任务类名称", + "description": "Template name", "name": "template", "in": "query" }, @@ -317,14 +288,14 @@ const docTemplate = `{ }, { "type": "boolean", - "description": "输出任务实例详情", + "description": "Output task details", "name": "verbose", "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "Task list result", "schema": { "$ref": "#/definitions/dao.ListTasksResult" } @@ -332,7 +303,7 @@ const docTemplate = `{ } }, "post": { - "description": "提交任务", + "description": "Submit task", "consumes": [ "application/json" ], @@ -340,12 +311,12 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "提交任务", + "summary": "Submit task", "parameters": [ { - "description": "任务对象", + "description": "Task object", "name": "task", "in": "body", "required": true, @@ -356,7 +327,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Task commit result (UUID, RunID)", "schema": { "$ref": "#/definitions/service.TaskCommitResult" } @@ -366,7 +337,7 @@ const docTemplate = `{ }, "/v1/tasks/{uuid}": { "get": { - "description": "获取任务元数据", + "description": "Get task metadata", "consumes": [ "application/json" ], @@ -374,13 +345,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "获取任务元数据", + "summary": "Get task metadata", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true @@ -388,7 +359,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Task object details", "schema": { "$ref": "#/definitions/dao.TaskRec" } @@ -396,7 +367,7 @@ const docTemplate = `{ } }, "delete": { - "description": "停止任务", + "description": "Stop task", "consumes": [ "application/json" ], @@ -404,13 +375,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "停止任务", + "summary": "Stop task", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true @@ -418,7 +389,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Operation success message", "schema": { "type": "string" } @@ -428,28 +399,29 @@ const docTemplate = `{ }, "/v1/tasks/{uuid}/logs": { "get": { - "description": "获取任务日志", + "description": "Get task logs with stream support (tail/follow) and regular pagination", "consumes": [ "application/json" ], "produces": [ - "application/json" + "application/json", + " plain/text" ], "tags": [ - "任务" + "Tasks" ], - "summary": "获取任务日志", + "summary": "Get task logs", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true }, { "type": "string", - "description": "任务实体,任务可能启动多个实体(如线程,POD)", + "description": "Entity that task may start multiple instances (e.g. threads, PODs)", "name": "entity", "in": "query" }, @@ -471,9 +443,27 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Streaming log output", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Invalid request", "schema": { - "$ref": "#/definitions/service.TaskLogsResult" + "$ref": "#/definitions/controllers.ResponseData" + } + }, + "404": { + "description": "Task not found", + "schema": { + "$ref": "#/definitions/controllers.ResponseData" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/controllers.ResponseData" } } } @@ -481,7 +471,7 @@ const docTemplate = `{ }, "/v1/tasks/{uuid}/status": { "get": { - "description": "获取任务状态", + "description": "Get task status", "consumes": [ "application/json" ], @@ -489,13 +479,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "获取任务状态", + "summary": "Get task status", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true @@ -503,7 +493,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Task status information", "schema": { "$ref": "#/definitions/service.TaskStatusResult" } @@ -513,7 +503,7 @@ const docTemplate = `{ }, "/v1/tasks/{uuid}/tags": { "get": { - "description": "获取任务标记", + "description": "Get task tags", "consumes": [ "application/json" ], @@ -521,13 +511,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "获取任务标记", + "summary": "Get task tags", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true @@ -535,7 +525,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Task tags", "schema": { "$ref": "#/definitions/service.TaskTagsResult" } @@ -543,7 +533,7 @@ const docTemplate = `{ } }, "post": { - "description": "给任务打标记,通常用于通知任务调度器对任务执行特定处置策略,比如标记为保障任务,空闲任务", + "description": "Tag task, usually to notify scheduler for specific handling strategy like guaranteed task or idle task", "consumes": [ "application/json" ], @@ -551,19 +541,19 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "给任务打标记", + "summary": "Tag task", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true }, { - "description": "标记内容,格式为Key=Value,可以同时有多组标记", + "description": "Tag content in Key=Value format, multiple tags can be set simultaneously", "name": "tags", "in": "body", "schema": { @@ -576,9 +566,9 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "All tags of the task", "schema": { - "type": "string" + "$ref": "#/definitions/service.TaskTagsResult" } } } @@ -586,7 +576,7 @@ const docTemplate = `{ }, "/v1/templates": { "get": { - "description": "任务模板", + "description": "Task templates", "consumes": [ "application/json" ], @@ -594,20 +584,20 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "列举任务模板", + "summary": "List task templates", "parameters": [ { "type": "boolean", - "description": "是否获取详情", + "description": "Include details", "name": "verbose", "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "List of task template names", "schema": { "type": "array", "items": { @@ -616,13 +606,13 @@ const docTemplate = `{ } }, "400": { - "description": "Bad Request", + "description": "Invalid request", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -630,7 +620,7 @@ const docTemplate = `{ } }, "post": { - "description": "创建任务模板", + "description": "Create task template", "consumes": [ "application/json" ], @@ -638,12 +628,12 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "创建任务模板", + "summary": "Create task template", "parameters": [ { - "description": "任务模板", + "description": "Template definition", "name": "templates", "in": "body", "required": true, @@ -654,7 +644,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Created template (ID+Name)", "schema": { "$ref": "#/definitions/controllers.AddTemplateResult" } @@ -664,7 +654,7 @@ const docTemplate = `{ }, "/v1/templates/{name}": { "get": { - "description": "获取任务模板", + "description": "Get task template", "consumes": [ "application/json" ], @@ -672,13 +662,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "获取任务模板", + "summary": "Get task template", "parameters": [ { "type": "string", - "description": "任务模板名称", + "description": "Template name", "name": "name", "in": "path", "required": true @@ -686,25 +676,25 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Task template details", "schema": { "$ref": "#/definitions/dao.TemplateRec" } }, "400": { - "description": "Bad Request", + "description": "Invalid request", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "404": { - "description": "Not Found", + "description": "Template not found", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -712,7 +702,7 @@ const docTemplate = `{ } }, "put": { - "description": "更新任务模板", + "description": "Update task template", "consumes": [ "application/json" ], @@ -720,19 +710,19 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "更新任务模板", + "summary": "Update task template", "parameters": [ { "type": "string", - "description": "任务模板名称", + "description": "Template name", "name": "name", "in": "path", "required": true }, { - "description": "任务模板", + "description": "Template definition", "name": "templates", "in": "body", "required": true, @@ -743,19 +733,19 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Template creation result (ID+Name)", "schema": { "$ref": "#/definitions/controllers.AddTemplateResult" } }, "400": { - "description": "Bad Request", + "description": "Invalid request", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -763,7 +753,7 @@ const docTemplate = `{ } }, "delete": { - "description": "删除任务模板", + "description": "Delete task template", "consumes": [ "application/json" ], @@ -771,13 +761,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "删除任务模板", + "summary": "Delete task template", "parameters": [ { "type": "string", - "description": "任务模板名称", + "description": "Template name", "name": "name", "in": "path", "required": true @@ -785,25 +775,25 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", + "description": "Delete success message", "schema": { "type": "string" } }, "400": { - "description": "Bad Request", + "description": "Tasks using this template exist", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "404": { - "description": "Not Found", + "description": "Template not found", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -854,19 +844,19 @@ const docTemplate = `{ "type": "object", "properties": { "id": { - "description": "记录ID", + "description": "record ID", "type": "integer" }, "pool_id": { - "description": "任务池ID", + "description": "pool ID", "type": "string" }, "res_name": { - "description": "资源名称", + "description": "resource name", "type": "string" }, "res_num": { - "description": "资源数量", + "description": "resource quantity", "type": "string" } } @@ -875,59 +865,55 @@ const docTemplate = `{ "type": "object", "properties": { "args": { - "description": "该任务的用户参数, JSON格式", + "description": "User arguments for task (JSON)", "type": "string" }, "callback": { - "description": "回调URL", + "description": "Callback URL", "type": "string" }, "created_by": { - "description": "创建者", + "description": "Creator", "type": "string" }, "extra": { - "description": "该任务模板的额外信息, JSON格式", + "description": "Extra info for template (JSON)", "type": "string" }, "name": { - "description": "任务名", + "description": "Task name", "type": "string" }, "namespace": { - "description": "数据空间名", + "description": "Namespace", "type": "string" }, "pool": { - "description": "任务池", + "description": "Task pool", "type": "string" }, "project": { - "description": "项目名", + "description": "Project name", "type": "string" }, "quotas": { - "description": "资源配额, JSON格式", + "description": "Resource quotas (JSON)", "type": "string" }, "tags": { - "description": "标记,可影响调度,JSON格式:[key=value]", + "description": "Tags affecting scheduling (JSON key=value)", "type": "string" }, "template": { - "description": "任务模板名", + "description": "Template name", "type": "string" }, "timeout": { - "description": "各阶段超时时间, JSON格式", - "type": "string" - }, - "updated_by": { - "description": "更新者", + "description": "Timeout settings (JSON)", "type": "string" }, "uuid": { - "description": "任务UUID", + "description": "Task UUID", "type": "string" } } @@ -936,99 +922,95 @@ const docTemplate = `{ "type": "object", "properties": { "args": { - "description": "该任务的用户参数, JSON格式", + "description": "User arguments for task (JSON)", "type": "string" }, "callback": { - "description": "回调URL", + "description": "Callback URL", "type": "string" }, "create_time": { - "description": "创建时间", + "description": "Creation time", "type": "string" }, "created_by": { - "description": "创建者", + "description": "Creator", "type": "string" }, "end_log": { - "description": "最终日志", + "description": "Final logs", "type": "string" }, "end_time": { - "description": "结束运行时间", + "description": "End time", "type": "string" }, "error": { - "description": "出错说明", + "description": "Error message", "type": "string" }, "extra": { - "description": "该任务模板的额外信息, JSON格式", + "description": "Extra info for template (JSON)", "type": "string" }, "name": { - "description": "任务名", + "description": "Task name", "type": "string" }, "namespace": { - "description": "数据空间名", + "description": "Namespace", "type": "string" }, "pool": { - "description": "任务池", + "description": "Task pool", "type": "string" }, "project": { - "description": "项目名", + "description": "Project name", "type": "string" }, "quotas": { - "description": "资源配额, JSON格式", + "description": "Resource quotas (JSON)", "type": "string" }, "running_time": { - "description": "开始运行时间", + "description": "Running start time", "type": "string" }, "start_time": { - "description": "启动时间", + "description": "Start time", "type": "string" }, "status": { - "description": "任务状态", + "description": "Task status", "type": "string" }, "tags": { - "description": "标记,可影响调度,JSON格式:[key=value]", + "description": "Tags affecting scheduling (JSON key=value)", "type": "string" }, "template": { - "description": "任务模板名", + "description": "Template name", "type": "string" }, "timeout": { - "description": "各阶段超时时间, JSON格式", + "description": "Timeout settings (JSON)", "type": "string" }, "update_time": { - "description": "最后更新时间", - "type": "string" - }, - "updated_by": { - "description": "更新者", + "description": "Last update time", "type": "string" }, "uuid": { - "description": "任务UUID", + "description": "Task UUID", "type": "string" }, "warning": { - "description": "告警信息", + "description": "Warning message", "type": "string" }, "yaml_content": { - "description": "部署文件内容", + "description": "Deployment file content", "type": "string" } } @@ -1085,19 +1067,19 @@ const docTemplate = `{ "type": "object", "properties": { "config": { - "description": "任务池配置,供各类型任务引擎使用", + "description": "pool configuration for various task engines", "type": "string" }, "description": { - "description": "任务池说明,展示任务池的关键信息,供用户了解任务池工作状况", + "description": "pool description showing key information for user understanding", "type": "string" }, "engine": { - "description": "采用的任务执行引擎", + "description": "task execution engine", "type": "string" }, "pool_id": { - "description": "任务池ID", + "description": "pool ID", "type": "string" }, "resources": { @@ -1107,11 +1089,11 @@ const docTemplate = `{ } }, "running": { - "description": "最大并发任务数", + "description": "maximum concurrent tasks", "type": "integer" }, "waiting": { - "description": "最大排队任务数", + "description": "maximum queued tasks", "type": "integer" } } @@ -1167,19 +1149,19 @@ const docTemplate = `{ "type": "object", "properties": { "allocate": { - "description": "分配量", + "description": "allocated amount", "type": "string" }, "capacity": { - "description": "配置量", + "description": "configured capacity", "type": "string" }, "name": { - "description": "资源名称", + "description": "resource name", "type": "string" }, "remain": { - "description": "实际残留", + "description": "actual remaining", "type": "string" } } @@ -1188,51 +1170,54 @@ const docTemplate = `{ "type": "object", "properties": { "create_time": { - "description": "入队时间", + "description": "queue time", "type": "string" }, "created_by": { - "description": "用户标记", + "description": "created by", "type": "string" }, "end_time": { - "description": "结束运行的时间", + "description": "end time", "type": "string" }, "error": { - "description": "出错说明", + "description": "error message", "type": "string" }, "name": { - "description": "任务名字", + "description": "task name", "type": "string" }, "pool": { - "description": "在哪个任务池运行", + "description": "running pool", "type": "string" }, "running_time": { - "description": "开始正常运行的时间", + "description": "actual running start time", "type": "string" }, "start_time": { - "description": "启动时间", + "description": "start time", "type": "string" }, "status": { - "description": "任务状态", + "description": "task status", "type": "string" }, "tags": { - "description": "标记", - "type": "string" + "description": "tags", + "type": "object", + "additionalProperties": { + "type": "string" + } }, "uuid": { - "description": "任务唯一ID", + "description": "task unique ID", "type": "string" }, "warning": { - "description": "告警信息", + "description": "warning message", "type": "string" } } @@ -1241,33 +1226,45 @@ const docTemplate = `{ "type": "object", "properties": { "config": { - "description": "任务池配置", + "description": "task pool configuration", + "type": "string" + }, + "engine": { + "description": "task pool engine", "type": "string" }, + "max_running": { + "description": "maximum parallel tasks", + "type": "integer" + }, + "max_waiting": { + "description": "maximum waiting tasks", + "type": "integer" + }, "pool_id": { - "description": "任务池标识", + "description": "Pool ID", "type": "string" }, "resources": { - "description": "该任务池的资源信息", + "description": "resource information of the pool", "type": "array", "items": { "$ref": "#/definitions/task.ResourceItem" } }, "running": { - "description": "正在该任务池运行的任务数", + "description": "current running tasks", "type": "integer" }, "tasks": { - "description": "等待该任务池或在其中运行的任务信息", + "description": "task information in queue or running", "type": "array", "items": { "$ref": "#/definitions/task.TaskInstanceSummary" } }, "waiting": { - "description": "正在等待该任务池的任务数", + "description": "current waiting tasks", "type": "integer" } } @@ -1276,19 +1273,31 @@ const docTemplate = `{ "type": "object", "properties": { "config": { - "description": "任务池配置", + "description": "Pool configuration", + "type": "string" + }, + "engine": { + "description": "Task engine used by pool", "type": "string" }, + "max_running": { + "description": "Maximum concurrent tasks", + "type": "integer" + }, + "max_waiting": { + "description": "Maximum queued tasks", + "type": "integer" + }, "pool_id": { - "description": "任务池标识", + "description": "Pool identifier", "type": "string" }, "running": { - "description": "正在该任务池运行的任务数", + "description": "Number of tasks currently running in pool", "type": "integer" }, "waiting": { - "description": "正在该任务池等待的任务数", + "description": "Number of tasks currently waiting in pool", "type": "integer" } } @@ -1298,12 +1307,12 @@ const docTemplate = `{ // SwaggerInfo holds exported Swagger Info so clients can modify it var SwaggerInfo = &swag.Spec{ - Version: "1.0 版本", + Version: "1.0", Host: "", BasePath: "/taskd/api", Schemes: []string{}, - Title: "任务管理", - Description: "任务管理", + Title: "Task Management", + Description: "Task Management System", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, LeftDelim: "{{", diff --git a/docs/swagger.json b/docs/swagger.json index 3a8570e..0d3a56a 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1,24 +1,24 @@ { "swagger": "2.0", "info": { - "description": "任务管理", - "title": "任务管理", + "description": "Task Management System", + "title": "Task Management", "termsOfService": "http://www.sangfor.com.cn", "contact": { - "name": "张钊晋,郑柏春", + "name": "Zhaojin Zhang,Bochun Zheng", "url": "http://www.sangfor.com.cn" }, "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.html" }, - "version": "1.0 版本" + "version": "1.0" }, "basePath": "/taskd/api", "paths": { "/v1/pools": { "get": { - "description": "列举任务池信息,比如资源用量,运行任务概况", + "description": "List task pool information including resource usage and running task overview", "consumes": [ "application/json" ], @@ -26,12 +26,12 @@ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "列举任务池", + "summary": "List task pools", "responses": { "200": { - "description": "OK", + "description": "Queue information", "schema": { "type": "array", "items": { @@ -42,7 +42,7 @@ } }, "post": { - "description": "添加一个任务池", + "description": "Add a task pool", "consumes": [ "application/json" ], @@ -50,12 +50,12 @@ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "添加一个任务池", + "summary": "Add a task pool", "parameters": [ { - "description": "任务池", + "description": "Task pool", "name": "pool", "in": "body", "required": true, @@ -66,7 +66,7 @@ ], "responses": { "200": { - "description": "OK", + "description": "Task pool result", "schema": { "$ref": "#/definitions/service.TaskPoolResult" } @@ -76,7 +76,7 @@ }, "/v1/pools/{name}": { "get": { - "description": "获取任务池详情", + "description": "Get task pool details", "consumes": [ "application/json" ], @@ -84,27 +84,27 @@ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "获取任务池详情", + "summary": "Get task pool details", "parameters": [ { "type": "string", - "description": "任务池名", + "description": "Pool name", "name": "name", "in": "path", "required": true }, { "type": "boolean", - "description": "是否获取详情", + "description": "Get detailed info", "name": "verbose", "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "Pool information", "schema": { "$ref": "#/definitions/task.TaskPoolDetail" } @@ -112,7 +112,7 @@ } }, "put": { - "description": "更新任务池定义", + "description": "Update task pool definition", "consumes": [ "application/json" ], @@ -120,19 +120,19 @@ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "更新任务池", + "summary": "Update task pool", "parameters": [ { "type": "string", - "description": "任务池ID", + "description": "Task pool ID", "name": "name", "in": "path", "required": true }, { - "description": "任务池", + "description": "Task pool", "name": "pools", "in": "body", "required": true, @@ -143,7 +143,7 @@ ], "responses": { "200": { - "description": "OK", + "description": "Update task pool", "schema": { "$ref": "#/definitions/service.TaskPoolResult" } @@ -151,7 +151,7 @@ } }, "delete": { - "description": "删除任务池,同时删除关联的PoolResource", + "description": "Delete task pool and associated PoolResource", "consumes": [ "application/json" ], @@ -159,13 +159,13 @@ "application/json" ], "tags": [ - "任务池" + "TaskPools" ], - "summary": "删除任务池", + "summary": "Delete task pool", "parameters": [ { "type": "string", - "description": "任务池名", + "description": "Pool name", "name": "name", "in": "path", "required": true @@ -173,54 +173,25 @@ ], "responses": { "200": { - "description": "OK", + "description": "Delete success message", "schema": { "type": "string" } }, "400": { - "description": "Bad Request", + "description": "Running tasks exist", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "404": { - "description": "Not Found", + "description": "Pool not found", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controllers.ResponseData" - } - } - } - } - }, - "/v1/reload": { - "post": { - "description": "重新加载任务池相关配置,适用于池节点变更,节点资源变更,池轮询策略变更", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "任务池" - ], - "summary": "重新加载任务池相关配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - }, - "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -230,7 +201,7 @@ }, "/v1/tasks": { "get": { - "description": "列举任务", + "description": "List tasks", "consumes": [ "application/json" ], @@ -238,67 +209,67 @@ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "列举任务", + "summary": "List tasks", "parameters": [ { "type": "string", - "description": "任务名称", + "description": "Task name", "name": "name", "in": "query" }, { "type": "string", - "description": "命名空间", + "description": "Namespace", "name": "namespace", "in": "query" }, { "type": "string", - "description": "任务属主", + "description": "Task owner", "name": "owner", "in": "query" }, { "type": "integer", - "description": "页码", + "description": "Page number", "name": "page", "in": "query" }, { "type": "integer", - "description": "每页数量", + "description": "Items per page", "name": "pageSize", "in": "query" }, { "type": "string", - "description": "待运行资源池", + "description": "Target resource pool", "name": "pool", "in": "query" }, { "type": "string", - "description": "项目名称", + "description": "Project name", "name": "project", "in": "query" }, { "type": "string", - "description": "排序字段", + "description": "Sort field", "name": "sort", "in": "query" }, { "type": "string", - "description": "任务状态", + "description": "Task status", "name": "status", "in": "query" }, { "type": "string", - "description": "任务类名称", + "description": "Template name", "name": "template", "in": "query" }, @@ -310,14 +281,14 @@ }, { "type": "boolean", - "description": "输出任务实例详情", + "description": "Output task details", "name": "verbose", "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "Task list result", "schema": { "$ref": "#/definitions/dao.ListTasksResult" } @@ -325,7 +296,7 @@ } }, "post": { - "description": "提交任务", + "description": "Submit task", "consumes": [ "application/json" ], @@ -333,12 +304,12 @@ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "提交任务", + "summary": "Submit task", "parameters": [ { - "description": "任务对象", + "description": "Task object", "name": "task", "in": "body", "required": true, @@ -349,7 +320,7 @@ ], "responses": { "200": { - "description": "OK", + "description": "Task commit result (UUID, RunID)", "schema": { "$ref": "#/definitions/service.TaskCommitResult" } @@ -359,7 +330,7 @@ }, "/v1/tasks/{uuid}": { "get": { - "description": "获取任务元数据", + "description": "Get task metadata", "consumes": [ "application/json" ], @@ -367,13 +338,13 @@ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "获取任务元数据", + "summary": "Get task metadata", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true @@ -381,7 +352,7 @@ ], "responses": { "200": { - "description": "OK", + "description": "Task object details", "schema": { "$ref": "#/definitions/dao.TaskRec" } @@ -389,7 +360,7 @@ } }, "delete": { - "description": "停止任务", + "description": "Stop task", "consumes": [ "application/json" ], @@ -397,13 +368,13 @@ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "停止任务", + "summary": "Stop task", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true @@ -411,7 +382,7 @@ ], "responses": { "200": { - "description": "OK", + "description": "Operation success message", "schema": { "type": "string" } @@ -421,28 +392,29 @@ }, "/v1/tasks/{uuid}/logs": { "get": { - "description": "获取任务日志", + "description": "Get task logs with stream support (tail/follow) and regular pagination", "consumes": [ "application/json" ], "produces": [ - "application/json" + "application/json", + " plain/text" ], "tags": [ - "任务" + "Tasks" ], - "summary": "获取任务日志", + "summary": "Get task logs", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true }, { "type": "string", - "description": "任务实体,任务可能启动多个实体(如线程,POD)", + "description": "Entity that task may start multiple instances (e.g. threads, PODs)", "name": "entity", "in": "query" }, @@ -464,9 +436,27 @@ ], "responses": { "200": { - "description": "OK", + "description": "Streaming log output", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Invalid request", "schema": { - "$ref": "#/definitions/service.TaskLogsResult" + "$ref": "#/definitions/controllers.ResponseData" + } + }, + "404": { + "description": "Task not found", + "schema": { + "$ref": "#/definitions/controllers.ResponseData" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/controllers.ResponseData" } } } @@ -474,7 +464,7 @@ }, "/v1/tasks/{uuid}/status": { "get": { - "description": "获取任务状态", + "description": "Get task status", "consumes": [ "application/json" ], @@ -482,13 +472,13 @@ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "获取任务状态", + "summary": "Get task status", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true @@ -496,7 +486,7 @@ ], "responses": { "200": { - "description": "OK", + "description": "Task status information", "schema": { "$ref": "#/definitions/service.TaskStatusResult" } @@ -506,7 +496,7 @@ }, "/v1/tasks/{uuid}/tags": { "get": { - "description": "获取任务标记", + "description": "Get task tags", "consumes": [ "application/json" ], @@ -514,13 +504,13 @@ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "获取任务标记", + "summary": "Get task tags", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true @@ -528,7 +518,7 @@ ], "responses": { "200": { - "description": "OK", + "description": "Task tags", "schema": { "$ref": "#/definitions/service.TaskTagsResult" } @@ -536,7 +526,7 @@ } }, "post": { - "description": "给任务打标记,通常用于通知任务调度器对任务执行特定处置策略,比如标记为保障任务,空闲任务", + "description": "Tag task, usually to notify scheduler for specific handling strategy like guaranteed task or idle task", "consumes": [ "application/json" ], @@ -544,19 +534,19 @@ "application/json" ], "tags": [ - "任务" + "Tasks" ], - "summary": "给任务打标记", + "summary": "Tag task", "parameters": [ { "type": "string", - "description": "任务UUID", + "description": "Task UUID", "name": "uuid", "in": "path", "required": true }, { - "description": "标记内容,格式为Key=Value,可以同时有多组标记", + "description": "Tag content in Key=Value format, multiple tags can be set simultaneously", "name": "tags", "in": "body", "schema": { @@ -569,9 +559,9 @@ ], "responses": { "200": { - "description": "OK", + "description": "All tags of the task", "schema": { - "type": "string" + "$ref": "#/definitions/service.TaskTagsResult" } } } @@ -579,7 +569,7 @@ }, "/v1/templates": { "get": { - "description": "任务模板", + "description": "Task templates", "consumes": [ "application/json" ], @@ -587,20 +577,20 @@ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "列举任务模板", + "summary": "List task templates", "parameters": [ { "type": "boolean", - "description": "是否获取详情", + "description": "Include details", "name": "verbose", "in": "query" } ], "responses": { "200": { - "description": "OK", + "description": "List of task template names", "schema": { "type": "array", "items": { @@ -609,13 +599,13 @@ } }, "400": { - "description": "Bad Request", + "description": "Invalid request", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -623,7 +613,7 @@ } }, "post": { - "description": "创建任务模板", + "description": "Create task template", "consumes": [ "application/json" ], @@ -631,12 +621,12 @@ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "创建任务模板", + "summary": "Create task template", "parameters": [ { - "description": "任务模板", + "description": "Template definition", "name": "templates", "in": "body", "required": true, @@ -647,7 +637,7 @@ ], "responses": { "200": { - "description": "OK", + "description": "Created template (ID+Name)", "schema": { "$ref": "#/definitions/controllers.AddTemplateResult" } @@ -657,7 +647,7 @@ }, "/v1/templates/{name}": { "get": { - "description": "获取任务模板", + "description": "Get task template", "consumes": [ "application/json" ], @@ -665,13 +655,13 @@ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "获取任务模板", + "summary": "Get task template", "parameters": [ { "type": "string", - "description": "任务模板名称", + "description": "Template name", "name": "name", "in": "path", "required": true @@ -679,25 +669,25 @@ ], "responses": { "200": { - "description": "OK", + "description": "Task template details", "schema": { "$ref": "#/definitions/dao.TemplateRec" } }, "400": { - "description": "Bad Request", + "description": "Invalid request", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "404": { - "description": "Not Found", + "description": "Template not found", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -705,7 +695,7 @@ } }, "put": { - "description": "更新任务模板", + "description": "Update task template", "consumes": [ "application/json" ], @@ -713,19 +703,19 @@ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "更新任务模板", + "summary": "Update task template", "parameters": [ { "type": "string", - "description": "任务模板名称", + "description": "Template name", "name": "name", "in": "path", "required": true }, { - "description": "任务模板", + "description": "Template definition", "name": "templates", "in": "body", "required": true, @@ -736,19 +726,19 @@ ], "responses": { "200": { - "description": "OK", + "description": "Template creation result (ID+Name)", "schema": { "$ref": "#/definitions/controllers.AddTemplateResult" } }, "400": { - "description": "Bad Request", + "description": "Invalid request", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -756,7 +746,7 @@ } }, "delete": { - "description": "删除任务模板", + "description": "Delete task template", "consumes": [ "application/json" ], @@ -764,13 +754,13 @@ "application/json" ], "tags": [ - "任务模板" + "TaskTemplates" ], - "summary": "删除任务模板", + "summary": "Delete task template", "parameters": [ { "type": "string", - "description": "任务模板名称", + "description": "Template name", "name": "name", "in": "path", "required": true @@ -778,25 +768,25 @@ ], "responses": { "200": { - "description": "OK", + "description": "Delete success message", "schema": { "type": "string" } }, "400": { - "description": "Bad Request", + "description": "Tasks using this template exist", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "404": { - "description": "Not Found", + "description": "Template not found", "schema": { "$ref": "#/definitions/controllers.ResponseData" } }, "500": { - "description": "Internal Server Error", + "description": "Internal server error", "schema": { "$ref": "#/definitions/controllers.ResponseData" } @@ -847,19 +837,19 @@ "type": "object", "properties": { "id": { - "description": "记录ID", + "description": "record ID", "type": "integer" }, "pool_id": { - "description": "任务池ID", + "description": "pool ID", "type": "string" }, "res_name": { - "description": "资源名称", + "description": "resource name", "type": "string" }, "res_num": { - "description": "资源数量", + "description": "resource quantity", "type": "string" } } @@ -868,59 +858,55 @@ "type": "object", "properties": { "args": { - "description": "该任务的用户参数, JSON格式", + "description": "User arguments for task (JSON)", "type": "string" }, "callback": { - "description": "回调URL", + "description": "Callback URL", "type": "string" }, "created_by": { - "description": "创建者", + "description": "Creator", "type": "string" }, "extra": { - "description": "该任务模板的额外信息, JSON格式", + "description": "Extra info for template (JSON)", "type": "string" }, "name": { - "description": "任务名", + "description": "Task name", "type": "string" }, "namespace": { - "description": "数据空间名", + "description": "Namespace", "type": "string" }, "pool": { - "description": "任务池", + "description": "Task pool", "type": "string" }, "project": { - "description": "项目名", + "description": "Project name", "type": "string" }, "quotas": { - "description": "资源配额, JSON格式", + "description": "Resource quotas (JSON)", "type": "string" }, "tags": { - "description": "标记,可影响调度,JSON格式:[key=value]", + "description": "Tags affecting scheduling (JSON key=value)", "type": "string" }, "template": { - "description": "任务模板名", + "description": "Template name", "type": "string" }, "timeout": { - "description": "各阶段超时时间, JSON格式", - "type": "string" - }, - "updated_by": { - "description": "更新者", + "description": "Timeout settings (JSON)", "type": "string" }, "uuid": { - "description": "任务UUID", + "description": "Task UUID", "type": "string" } } @@ -929,99 +915,95 @@ "type": "object", "properties": { "args": { - "description": "该任务的用户参数, JSON格式", + "description": "User arguments for task (JSON)", "type": "string" }, "callback": { - "description": "回调URL", + "description": "Callback URL", "type": "string" }, "create_time": { - "description": "创建时间", + "description": "Creation time", "type": "string" }, "created_by": { - "description": "创建者", + "description": "Creator", "type": "string" }, "end_log": { - "description": "最终日志", + "description": "Final logs", "type": "string" }, "end_time": { - "description": "结束运行时间", + "description": "End time", "type": "string" }, "error": { - "description": "出错说明", + "description": "Error message", "type": "string" }, "extra": { - "description": "该任务模板的额外信息, JSON格式", + "description": "Extra info for template (JSON)", "type": "string" }, "name": { - "description": "任务名", + "description": "Task name", "type": "string" }, "namespace": { - "description": "数据空间名", + "description": "Namespace", "type": "string" }, "pool": { - "description": "任务池", + "description": "Task pool", "type": "string" }, "project": { - "description": "项目名", + "description": "Project name", "type": "string" }, "quotas": { - "description": "资源配额, JSON格式", + "description": "Resource quotas (JSON)", "type": "string" }, "running_time": { - "description": "开始运行时间", + "description": "Running start time", "type": "string" }, "start_time": { - "description": "启动时间", + "description": "Start time", "type": "string" }, "status": { - "description": "任务状态", + "description": "Task status", "type": "string" }, "tags": { - "description": "标记,可影响调度,JSON格式:[key=value]", + "description": "Tags affecting scheduling (JSON key=value)", "type": "string" }, "template": { - "description": "任务模板名", + "description": "Template name", "type": "string" }, "timeout": { - "description": "各阶段超时时间, JSON格式", + "description": "Timeout settings (JSON)", "type": "string" }, "update_time": { - "description": "最后更新时间", - "type": "string" - }, - "updated_by": { - "description": "更新者", + "description": "Last update time", "type": "string" }, "uuid": { - "description": "任务UUID", + "description": "Task UUID", "type": "string" }, "warning": { - "description": "告警信息", + "description": "Warning message", "type": "string" }, "yaml_content": { - "description": "部署文件内容", + "description": "Deployment file content", "type": "string" } } @@ -1078,19 +1060,19 @@ "type": "object", "properties": { "config": { - "description": "任务池配置,供各类型任务引擎使用", + "description": "pool configuration for various task engines", "type": "string" }, "description": { - "description": "任务池说明,展示任务池的关键信息,供用户了解任务池工作状况", + "description": "pool description showing key information for user understanding", "type": "string" }, "engine": { - "description": "采用的任务执行引擎", + "description": "task execution engine", "type": "string" }, "pool_id": { - "description": "任务池ID", + "description": "pool ID", "type": "string" }, "resources": { @@ -1100,11 +1082,11 @@ } }, "running": { - "description": "最大并发任务数", + "description": "maximum concurrent tasks", "type": "integer" }, "waiting": { - "description": "最大排队任务数", + "description": "maximum queued tasks", "type": "integer" } } @@ -1160,19 +1142,19 @@ "type": "object", "properties": { "allocate": { - "description": "分配量", + "description": "allocated amount", "type": "string" }, "capacity": { - "description": "配置量", + "description": "configured capacity", "type": "string" }, "name": { - "description": "资源名称", + "description": "resource name", "type": "string" }, "remain": { - "description": "实际残留", + "description": "actual remaining", "type": "string" } } @@ -1181,51 +1163,54 @@ "type": "object", "properties": { "create_time": { - "description": "入队时间", + "description": "queue time", "type": "string" }, "created_by": { - "description": "用户标记", + "description": "created by", "type": "string" }, "end_time": { - "description": "结束运行的时间", + "description": "end time", "type": "string" }, "error": { - "description": "出错说明", + "description": "error message", "type": "string" }, "name": { - "description": "任务名字", + "description": "task name", "type": "string" }, "pool": { - "description": "在哪个任务池运行", + "description": "running pool", "type": "string" }, "running_time": { - "description": "开始正常运行的时间", + "description": "actual running start time", "type": "string" }, "start_time": { - "description": "启动时间", + "description": "start time", "type": "string" }, "status": { - "description": "任务状态", + "description": "task status", "type": "string" }, "tags": { - "description": "标记", - "type": "string" + "description": "tags", + "type": "object", + "additionalProperties": { + "type": "string" + } }, "uuid": { - "description": "任务唯一ID", + "description": "task unique ID", "type": "string" }, "warning": { - "description": "告警信息", + "description": "warning message", "type": "string" } } @@ -1234,33 +1219,45 @@ "type": "object", "properties": { "config": { - "description": "任务池配置", + "description": "task pool configuration", + "type": "string" + }, + "engine": { + "description": "task pool engine", "type": "string" }, + "max_running": { + "description": "maximum parallel tasks", + "type": "integer" + }, + "max_waiting": { + "description": "maximum waiting tasks", + "type": "integer" + }, "pool_id": { - "description": "任务池标识", + "description": "Pool ID", "type": "string" }, "resources": { - "description": "该任务池的资源信息", + "description": "resource information of the pool", "type": "array", "items": { "$ref": "#/definitions/task.ResourceItem" } }, "running": { - "description": "正在该任务池运行的任务数", + "description": "current running tasks", "type": "integer" }, "tasks": { - "description": "等待该任务池或在其中运行的任务信息", + "description": "task information in queue or running", "type": "array", "items": { "$ref": "#/definitions/task.TaskInstanceSummary" } }, "waiting": { - "description": "正在等待该任务池的任务数", + "description": "current waiting tasks", "type": "integer" } } @@ -1269,19 +1266,31 @@ "type": "object", "properties": { "config": { - "description": "任务池配置", + "description": "Pool configuration", + "type": "string" + }, + "engine": { + "description": "Task engine used by pool", "type": "string" }, + "max_running": { + "description": "Maximum concurrent tasks", + "type": "integer" + }, + "max_waiting": { + "description": "Maximum queued tasks", + "type": "integer" + }, "pool_id": { - "description": "任务池标识", + "description": "Pool identifier", "type": "string" }, "running": { - "description": "正在该任务池运行的任务数", + "description": "Number of tasks currently running in pool", "type": "integer" }, "waiting": { - "description": "正在该任务池等待的任务数", + "description": "Number of tasks currently waiting in pool", "type": "integer" } } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 8b4aa6d..ef56e9d 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -27,136 +27,130 @@ definitions: dao.PoolResource: properties: id: - description: 记录ID + description: record ID type: integer pool_id: - description: 任务池ID + description: pool ID type: string res_name: - description: 资源名称 + description: resource name type: string res_num: - description: 资源数量 + description: resource quantity type: string type: object dao.TaskObjRec: properties: args: - description: 该任务的用户参数, JSON格式 + description: User arguments for task (JSON) type: string callback: - description: 回调URL + description: Callback URL type: string created_by: - description: 创建者 + description: Creator type: string extra: - description: 该任务模板的额外信息, JSON格式 + description: Extra info for template (JSON) type: string name: - description: 任务名 + description: Task name type: string namespace: - description: 数据空间名 + description: Namespace type: string pool: - description: 任务池 + description: Task pool type: string project: - description: 项目名 + description: Project name type: string quotas: - description: 资源配额, JSON格式 + description: Resource quotas (JSON) type: string tags: - description: 标记,可影响调度,JSON格式:[key=value] + description: Tags affecting scheduling (JSON key=value) type: string template: - description: 任务模板名 + description: Template name type: string timeout: - description: 各阶段超时时间, JSON格式 - type: string - updated_by: - description: 更新者 + description: Timeout settings (JSON) type: string uuid: - description: 任务UUID + description: Task UUID type: string type: object dao.TaskRec: properties: args: - description: 该任务的用户参数, JSON格式 + description: User arguments for task (JSON) type: string callback: - description: 回调URL + description: Callback URL type: string create_time: - description: 创建时间 + description: Creation time type: string created_by: - description: 创建者 + description: Creator type: string end_log: - description: 最终日志 + description: Final logs type: string end_time: - description: 结束运行时间 + description: End time type: string error: - description: 出错说明 + description: Error message type: string extra: - description: 该任务模板的额外信息, JSON格式 + description: Extra info for template (JSON) type: string name: - description: 任务名 + description: Task name type: string namespace: - description: 数据空间名 + description: Namespace type: string pool: - description: 任务池 + description: Task pool type: string project: - description: 项目名 + description: Project name type: string quotas: - description: 资源配额, JSON格式 + description: Resource quotas (JSON) type: string running_time: - description: 开始运行时间 + description: Running start time type: string start_time: - description: 启动时间 + description: Start time type: string status: - description: 任务状态 + description: Task status type: string tags: - description: 标记,可影响调度,JSON格式:[key=value] + description: Tags affecting scheduling (JSON key=value) type: string template: - description: 任务模板名 + description: Template name type: string timeout: - description: 各阶段超时时间, JSON格式 + description: Timeout settings (JSON) type: string update_time: - description: 最后更新时间 - type: string - updated_by: - description: 更新者 + description: Last update time type: string uuid: - description: 任务UUID + description: Task UUID type: string warning: - description: 告警信息 + description: Warning message type: string yaml_content: - description: 部署文件内容 + description: Deployment file content type: string type: object dao.TemplateRec: @@ -193,26 +187,26 @@ definitions: service.TaskPoolArgs: properties: config: - description: 任务池配置,供各类型任务引擎使用 + description: pool configuration for various task engines type: string description: - description: 任务池说明,展示任务池的关键信息,供用户了解任务池工作状况 + description: pool description showing key information for user understanding type: string engine: - description: 采用的任务执行引擎 + description: task execution engine type: string pool_id: - description: 任务池ID + description: pool ID type: string resources: items: $ref: '#/definitions/dao.PoolResource' type: array running: - description: 最大并发任务数 + description: maximum concurrent tasks type: integer waiting: - description: 最大排队任务数 + description: maximum queued tasks type: integer type: object service.TaskPoolResult: @@ -248,132 +242,153 @@ definitions: task.ResourceItem: properties: allocate: - description: 分配量 + description: allocated amount type: string capacity: - description: 配置量 + description: configured capacity type: string name: - description: 资源名称 + description: resource name type: string remain: - description: 实际残留 + description: actual remaining type: string type: object task.TaskInstanceSummary: properties: create_time: - description: 入队时间 + description: queue time type: string created_by: - description: 用户标记 + description: created by type: string end_time: - description: 结束运行的时间 + description: end time type: string error: - description: 出错说明 + description: error message type: string name: - description: 任务名字 + description: task name type: string pool: - description: 在哪个任务池运行 + description: running pool type: string running_time: - description: 开始正常运行的时间 + description: actual running start time type: string start_time: - description: 启动时间 + description: start time type: string status: - description: 任务状态 + description: task status type: string tags: - description: 标记 - type: string + additionalProperties: + type: string + description: tags + type: object uuid: - description: 任务唯一ID + description: task unique ID type: string warning: - description: 告警信息 + description: warning message type: string type: object task.TaskPoolDetail: properties: config: - description: 任务池配置 + description: task pool configuration + type: string + engine: + description: task pool engine type: string + max_running: + description: maximum parallel tasks + type: integer + max_waiting: + description: maximum waiting tasks + type: integer pool_id: - description: 任务池标识 + description: Pool ID type: string resources: - description: 该任务池的资源信息 + description: resource information of the pool items: $ref: '#/definitions/task.ResourceItem' type: array running: - description: 正在该任务池运行的任务数 + description: current running tasks type: integer tasks: - description: 等待该任务池或在其中运行的任务信息 + description: task information in queue or running items: $ref: '#/definitions/task.TaskInstanceSummary' type: array waiting: - description: 正在等待该任务池的任务数 + description: current waiting tasks type: integer type: object task.TaskPoolSummary: properties: config: - description: 任务池配置 + description: Pool configuration type: string + engine: + description: Task engine used by pool + type: string + max_running: + description: Maximum concurrent tasks + type: integer + max_waiting: + description: Maximum queued tasks + type: integer pool_id: - description: 任务池标识 + description: Pool identifier type: string running: - description: 正在该任务池运行的任务数 + description: Number of tasks currently running in pool type: integer waiting: - description: 正在该任务池等待的任务数 + description: Number of tasks currently waiting in pool type: integer type: object info: contact: - name: 张钊晋,郑柏春 + name: Zhaojin Zhang,Bochun Zheng url: http://www.sangfor.com.cn - description: 任务管理 + description: Task Management System license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html termsOfService: http://www.sangfor.com.cn - title: 任务管理 - version: 1.0 版本 + title: Task Management + version: "1.0" paths: /v1/pools: get: consumes: - application/json - description: 列举任务池信息,比如资源用量,运行任务概况 + description: List task pool information including resource usage and running + task overview produces: - application/json responses: "200": - description: OK + description: Queue information schema: items: $ref: '#/definitions/task.TaskPoolSummary' type: array - summary: 列举任务池 + summary: List task pools tags: - - 任务池 + - TaskPools post: consumes: - application/json - description: 添加一个任务池 + description: Add a task pool parameters: - - description: 任务池 + - description: Task pool in: body name: pool required: true @@ -383,19 +398,19 @@ paths: - application/json responses: "200": - description: OK + description: Task pool result schema: $ref: '#/definitions/service.TaskPoolResult' - summary: 添加一个任务池 + summary: Add a task pool tags: - - 任务池 + - TaskPools /v1/pools/{name}: delete: consumes: - application/json - description: 删除任务池,同时删除关联的PoolResource + description: Delete task pool and associated PoolResource parameters: - - description: 任务池名 + - description: Pool name in: path name: name required: true @@ -404,35 +419,35 @@ paths: - application/json responses: "200": - description: OK + description: Delete success message schema: type: string "400": - description: Bad Request + description: Running tasks exist schema: $ref: '#/definitions/controllers.ResponseData' "404": - description: Not Found + description: Pool not found schema: $ref: '#/definitions/controllers.ResponseData' "500": - description: Internal Server Error + description: Internal server error schema: $ref: '#/definitions/controllers.ResponseData' - summary: 删除任务池 + summary: Delete task pool tags: - - 任务池 + - TaskPools get: consumes: - application/json - description: 获取任务池详情 + description: Get task pool details parameters: - - description: 任务池名 + - description: Pool name in: path name: name required: true type: string - - description: 是否获取详情 + - description: Get detailed info in: query name: verbose type: boolean @@ -440,23 +455,23 @@ paths: - application/json responses: "200": - description: OK + description: Pool information schema: $ref: '#/definitions/task.TaskPoolDetail' - summary: 获取任务池详情 + summary: Get task pool details tags: - - 任务池 + - TaskPools put: consumes: - application/json - description: 更新任务池定义 + description: Update task pool definition parameters: - - description: 任务池ID + - description: Task pool ID in: path name: name required: true type: string - - description: 任务池 + - description: Task pool in: body name: pools required: true @@ -466,74 +481,55 @@ paths: - application/json responses: "200": - description: OK + description: Update task pool schema: $ref: '#/definitions/service.TaskPoolResult' - summary: 更新任务池 + summary: Update task pool tags: - - 任务池 - /v1/reload: - post: - consumes: - - application/json - description: 重新加载任务池相关配置,适用于池节点变更,节点资源变更,池轮询策略变更 - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/controllers.ResponseData' - summary: 重新加载任务池相关配置 - tags: - - 任务池 + - TaskPools /v1/tasks: get: consumes: - application/json - description: 列举任务 + description: List tasks parameters: - - description: 任务名称 + - description: Task name in: query name: name type: string - - description: 命名空间 + - description: Namespace in: query name: namespace type: string - - description: 任务属主 + - description: Task owner in: query name: owner type: string - - description: 页码 + - description: Page number in: query name: page type: integer - - description: 每页数量 + - description: Items per page in: query name: pageSize type: integer - - description: 待运行资源池 + - description: Target resource pool in: query name: pool type: string - - description: 项目名称 + - description: Project name in: query name: project type: string - - description: 排序字段 + - description: Sort field in: query name: sort type: string - - description: 任务状态 + - description: Task status in: query name: status type: string - - description: 任务类名称 + - description: Template name in: query name: template type: string @@ -541,7 +537,7 @@ paths: in: query name: uuid type: string - - description: 输出任务实例详情 + - description: Output task details in: query name: verbose type: boolean @@ -549,18 +545,18 @@ paths: - application/json responses: "200": - description: OK + description: Task list result schema: $ref: '#/definitions/dao.ListTasksResult' - summary: 列举任务 + summary: List tasks tags: - - 任务 + - Tasks post: consumes: - application/json - description: 提交任务 + description: Submit task parameters: - - description: 任务对象 + - description: Task object in: body name: task required: true @@ -570,19 +566,19 @@ paths: - application/json responses: "200": - description: OK + description: Task commit result (UUID, RunID) schema: $ref: '#/definitions/service.TaskCommitResult' - summary: 提交任务 + summary: Submit task tags: - - 任务 + - Tasks /v1/tasks/{uuid}: delete: consumes: - application/json - description: 停止任务 + description: Stop task parameters: - - description: 任务UUID + - description: Task UUID in: path name: uuid required: true @@ -591,18 +587,18 @@ paths: - application/json responses: "200": - description: OK + description: Operation success message schema: type: string - summary: 停止任务 + summary: Stop task tags: - - 任务 + - Tasks get: consumes: - application/json - description: 获取任务元数据 + description: Get task metadata parameters: - - description: 任务UUID + - description: Task UUID in: path name: uuid required: true @@ -611,24 +607,25 @@ paths: - application/json responses: "200": - description: OK + description: Task object details schema: $ref: '#/definitions/dao.TaskRec' - summary: 获取任务元数据 + summary: Get task metadata tags: - - 任务 + - Tasks /v1/tasks/{uuid}/logs: get: consumes: - application/json - description: 获取任务日志 + description: Get task logs with stream support (tail/follow) and regular pagination parameters: - - description: 任务UUID + - description: Task UUID in: path name: uuid required: true type: string - - description: 任务实体,任务可能启动多个实体(如线程,POD) + - description: Entity that task may start multiple instances (e.g. threads, + PODs) in: query name: entity type: string @@ -643,21 +640,34 @@ paths: type: boolean produces: - application/json + - ' plain/text' responses: "200": - description: OK + description: Streaming log output + schema: + type: string + "400": + description: Invalid request schema: - $ref: '#/definitions/service.TaskLogsResult' - summary: 获取任务日志 + $ref: '#/definitions/controllers.ResponseData' + "404": + description: Task not found + schema: + $ref: '#/definitions/controllers.ResponseData' + "500": + description: Internal server error + schema: + $ref: '#/definitions/controllers.ResponseData' + summary: Get task logs tags: - - 任务 + - Tasks /v1/tasks/{uuid}/status: get: consumes: - application/json - description: 获取任务状态 + description: Get task status parameters: - - description: 任务UUID + - description: Task UUID in: path name: uuid required: true @@ -666,19 +676,19 @@ paths: - application/json responses: "200": - description: OK + description: Task status information schema: $ref: '#/definitions/service.TaskStatusResult' - summary: 获取任务状态 + summary: Get task status tags: - - 任务 + - Tasks /v1/tasks/{uuid}/tags: get: consumes: - application/json - description: 获取任务标记 + description: Get task tags parameters: - - description: 任务UUID + - description: Task UUID in: path name: uuid required: true @@ -687,23 +697,24 @@ paths: - application/json responses: "200": - description: OK + description: Task tags schema: $ref: '#/definitions/service.TaskTagsResult' - summary: 获取任务标记 + summary: Get task tags tags: - - 任务 + - Tasks post: consumes: - application/json - description: 给任务打标记,通常用于通知任务调度器对任务执行特定处置策略,比如标记为保障任务,空闲任务 + description: Tag task, usually to notify scheduler for specific handling strategy + like guaranteed task or idle task parameters: - - description: 任务UUID + - description: Task UUID in: path name: uuid required: true type: string - - description: 标记内容,格式为Key=Value,可以同时有多组标记 + - description: Tag content in Key=Value format, multiple tags can be set simultaneously in: body name: tags schema: @@ -714,19 +725,19 @@ paths: - application/json responses: "200": - description: OK + description: All tags of the task schema: - type: string - summary: 给任务打标记 + $ref: '#/definitions/service.TaskTagsResult' + summary: Tag task tags: - - 任务 + - Tasks /v1/templates: get: consumes: - application/json - description: 任务模板 + description: Task templates parameters: - - description: 是否获取详情 + - description: Include details in: query name: verbose type: boolean @@ -734,28 +745,28 @@ paths: - application/json responses: "200": - description: OK + description: List of task template names schema: items: $ref: '#/definitions/dao.TemplateRec' type: array "400": - description: Bad Request + description: Invalid request schema: $ref: '#/definitions/controllers.ResponseData' "500": - description: Internal Server Error + description: Internal server error schema: $ref: '#/definitions/controllers.ResponseData' - summary: 列举任务模板 + summary: List task templates tags: - - 任务模板 + - TaskTemplates post: consumes: - application/json - description: 创建任务模板 + description: Create task template parameters: - - description: 任务模板 + - description: Template definition in: body name: templates required: true @@ -765,19 +776,19 @@ paths: - application/json responses: "200": - description: OK + description: Created template (ID+Name) schema: $ref: '#/definitions/controllers.AddTemplateResult' - summary: 创建任务模板 + summary: Create task template tags: - - 任务模板 + - TaskTemplates /v1/templates/{name}: delete: consumes: - application/json - description: 删除任务模板 + description: Delete task template parameters: - - description: 任务模板名称 + - description: Template name in: path name: name required: true @@ -786,30 +797,30 @@ paths: - application/json responses: "200": - description: OK + description: Delete success message schema: type: string "400": - description: Bad Request + description: Tasks using this template exist schema: $ref: '#/definitions/controllers.ResponseData' "404": - description: Not Found + description: Template not found schema: $ref: '#/definitions/controllers.ResponseData' "500": - description: Internal Server Error + description: Internal server error schema: $ref: '#/definitions/controllers.ResponseData' - summary: 删除任务模板 + summary: Delete task template tags: - - 任务模板 + - TaskTemplates get: consumes: - application/json - description: 获取任务模板 + description: Get task template parameters: - - description: 任务模板名称 + - description: Template name in: path name: name required: true @@ -818,35 +829,35 @@ paths: - application/json responses: "200": - description: OK + description: Task template details schema: $ref: '#/definitions/dao.TemplateRec' "400": - description: Bad Request + description: Invalid request schema: $ref: '#/definitions/controllers.ResponseData' "404": - description: Not Found + description: Template not found schema: $ref: '#/definitions/controllers.ResponseData' "500": - description: Internal Server Error + description: Internal server error schema: $ref: '#/definitions/controllers.ResponseData' - summary: 获取任务模板 + summary: Get task template tags: - - 任务模板 + - TaskTemplates put: consumes: - application/json - description: 更新任务模板 + description: Update task template parameters: - - description: 任务模板名称 + - description: Template name in: path name: name required: true type: string - - description: 任务模板 + - description: Template definition in: body name: templates required: true @@ -856,18 +867,18 @@ paths: - application/json responses: "200": - description: OK + description: Template creation result (ID+Name) schema: $ref: '#/definitions/controllers.AddTemplateResult' "400": - description: Bad Request + description: Invalid request schema: $ref: '#/definitions/controllers.ResponseData' "500": - description: Internal Server Error + description: Internal server error schema: $ref: '#/definitions/controllers.ResponseData' - summary: 更新任务模板 + summary: Update task template tags: - - 任务模板 + - TaskTemplates swagger: "2.0" diff --git a/internal/flow/keeper_test.go b/internal/flow/keeper_test.go index 694be9e..ff4a9c8 100644 --- a/internal/flow/keeper_test.go +++ b/internal/flow/keeper_test.go @@ -1,11 +1,13 @@ package flow import ( + "fmt" "io" "reflect" - "sync" + "taskd/dao" "taskd/internal/task" "testing" + "time" "github.com/agiledragon/gomonkey/v2" . "github.com/smartystreets/goconvey/convey" @@ -50,208 +52,332 @@ func TestHandleRunningJob_CompletedStatus(t *testing.T) { Convey("当作业状态已完成时,应该调用 sendFinishedChan", t, func() { job := &mockTaskJob{status: task.TaskStatusSucceeded} tp := &task.TaskPool{} + job.AttachPool(tp) sendFinishedChanCalled := false - gomonkey.ApplyFunc(tp.SendFinishedChan, func(task.TaskJob) { + gomonkey.ApplyMethod(reflect.TypeOf(tp), "SendFinishedChan", func(_ *task.TaskPool, job task.TaskJob) { sendFinishedChanCalled = true }) + gomonkey.ApplyFunc(dao.SetJSON, func(string, any, time.Duration) error { + return nil + }) dealRunningJob(job) So(sendFinishedChanCalled, ShouldBeTrue) }) } -// Test case 2: Verify behavior when job status is unfinished, expect dealRunningJob and resolveMetrics to be called -func TestHandleRunningJob_UnfinishedStatus(t *testing.T) { - Convey("当作业状态未完成时,应该调用 dealRunningJob 和 resolveMetrics", t, func() { - job := &mockTaskJob{status: task.TaskStatusRunning} +func TestInit(t *testing.T) { + Convey("测试初始化函数", t, func() { + Convey("正常初始化", func() { + patches := gomonkey.ApplyFunc(initPools, func() error { + return nil + }) + defer patches.Reset() - patches := gomonkey.ApplyFunc(dealRunningJob, func(task.TaskJob, func(task.TaskJob)) {}) - defer patches.Reset() + err := Init() + So(err, ShouldBeNil) + So(allJobs, ShouldNotBeNil) + So(allPools, ShouldNotBeNil) + }) + + Convey("初始化pool失败", func() { + patches := gomonkey.ApplyFunc(initPools, func() error { + return fmt.Errorf("init pools failed") + }) + defer patches.Reset() - processRunningJobCalled := false - patches.ApplyFunc(dealRunningJob, func(task.TaskJob, func(task.TaskJob)) { - processRunningJobCalled = true + err := Init() + So(err, ShouldNotBeNil) }) + }) +} + +func TestReloadPoolConfigs(t *testing.T) { + Convey("测试重载池配置", t, func() { + mockPool := &task.TaskPool{} + mockPool.Pool.PoolId = "test-pool" + + allPools = map[string]*task.TaskPool{ + "test-pool": mockPool, + } - resolveMetricsCalled := false - patches.ApplyFunc(resolveMetrics, func(*task.Metric) { - resolveMetricsCalled = true + Convey("重载存在的池", func() { + patches := gomonkey.ApplyMethod(reflect.TypeOf(mockPool), "ReloadResources", func(*task.TaskPool) error { + return nil + }) + defer patches.Reset() + + err := ReloadPoolConfigs("test-pool") + So(err, ShouldBeNil) }) - dealRunningJob(job) + Convey("重载不存在的池", func() { + err := ReloadPoolConfigs("non-existent-pool") + So(err, ShouldBeNil) + }) - So(processRunningJobCalled, ShouldBeTrue) - So(resolveMetricsCalled, ShouldBeTrue) + Convey("重载失败", func() { + patches := gomonkey.ApplyMethod(reflect.TypeOf(mockPool), "ReloadResources", func(*task.TaskPool) error { + return fmt.Errorf("reload failed") + }) + defer patches.Reset() + + err := ReloadPoolConfigs("test-pool") + So(err, ShouldNotBeNil) + }) }) } -// Test case 3: Verify job status transition during dealRunningJob processing -func TestHandleRunningJob_TransitionWithinProcess(t *testing.T) { - Convey("当在进行 dealRunningJob 处理时,作业状态由未完成变更为完成", t, func() { - job := &mockTaskJob{status: task.TaskStatusRunning} - tp := &task.TaskPool{} +func TestReloadHistoryTasks(t *testing.T) { + Convey("测试重载历史任务", t, func() { + Convey("没有未完成任务", func() { + patches := gomonkey.ApplyFunc(dao.LoadTasks_NotFinished, func() ([]dao.TaskRec, error) { + return []dao.TaskRec{}, nil + }) + defer patches.Reset() - patches := gomonkey.ApplyFunc(dealRunningJob, func(task.TaskJob, func(task.TaskJob)) { - patch := gomonkey.ApplyMethod(reflect.TypeOf(job), "FetchStatus", func() task.TaskStatus { return task.TaskStatusSucceeded }) - defer patch.Reset() + err := ReloadHistoryTasks() + So(err, ShouldBeNil) }) - defer patches.Reset() - sendFinishedChanCalled := false - gomonkey.ApplyFunc(tp.SendFinishedChan, func(task.TaskJob) { - sendFinishedChanCalled = true + Convey("有未完成任务", func() { + testTasks := []dao.TaskRec{ + {TaskObjRec: dao.TaskObjRec{UUID: "task1", Template: "template1"}}, + {TaskObjRec: dao.TaskObjRec{UUID: "task2", Template: "template2"}}, + } + + patches := gomonkey.ApplyFunc(dao.LoadTasks_NotFinished, func() ([]dao.TaskRec, error) { + return testTasks, nil + }) + patches.ApplyFunc(PoolNewJob, func(tr *dao.TaskRec) (task.TaskJob, error) { + return &mockTaskJob{}, nil + }) + defer patches.Reset() + + err := ReloadHistoryTasks() + So(err, ShouldBeNil) }) - dealRunningJob(job) + Convey("加载任务失败", func() { + patches := gomonkey.ApplyFunc(dao.LoadTasks_NotFinished, func() ([]dao.TaskRec, error) { + return nil, fmt.Errorf("load failed") + }) + defer patches.Reset() - So(sendFinishedChanCalled, ShouldBeTrue) + err := ReloadHistoryTasks() + So(err, ShouldNotBeNil) + }) }) } -// Test case 4: Test various job statuses to ensure each works as expected -func TestHandleRunningJob_VariousJobStatuses(t *testing.T) { - Convey("在不同的作业状态下,确保功能按预期工作", t, func() { - job := &mockTaskJob{status: task.TaskStatusRunning} - tp := &task.TaskPool{} +func TestListPools(t *testing.T) { + Convey("测试ListPools函数", t, func() { + pool1 := &task.TaskPool{} + pool1.Pool.PoolId = "pool1" + pool2 := &task.TaskPool{} + pool2.Pool.PoolId = "pool2" - patches := gomonkey.ApplyFunc(dealRunningJob, func(task.TaskJob, func(task.TaskJob)) {}) - defer patches.Reset() - - tests := []struct { - name string - status task.TaskStatus - expectedPhase task.TaskPhase - }{ - {"Queued", task.TaskStatusQueue, task.PhaseQueue}, - {"Running", task.TaskStatusRunning, task.PhaseRunning}, - {"Waiting", task.TaskStatusInit, task.PhaseInit}, + allPools = map[string]*task.TaskPool{ + "pool1": pool1, + "pool2": pool2, } - for _, tt := range tests { - job.status = tt.status - sendFinishedChanCalled := false - gomonkey.ApplyFunc(tp.SendFinishedChan, func(task.TaskJob) { - sendFinishedChanCalled = true - }) + pools := ListPools() + So(len(pools), ShouldEqual, 2) + So(pools[0].PoolId, ShouldEqual, "pool1") + So(pools[1].PoolId, ShouldEqual, "pool2") + }) +} - dealRunningJob(job) - So(sendFinishedChanCalled, ShouldBeFalse) +func TestGetPool(t *testing.T) { + Convey("测试GetPool函数", t, func() { + testPool := &task.TaskPool{} + testPool.Pool.PoolId = "test-pool" + allPools = map[string]*task.TaskPool{ + "test-pool": testPool, } + + Convey("获取存在的池", func() { + pool := GetPool("test-pool") + So(pool, ShouldEqual, testPool) + }) + + Convey("获取不存在的池", func() { + pool := GetPool("non-existent-pool") + So(pool, ShouldBeNil) + }) }) } -// Test case 5: Verify exception handling in dealRunningJob and resolveMetrics -func TestHandleRunningJob_HandleExceptions(t *testing.T) { - Convey("当 dealRunningJob 和 resolveMetrics 中出现异常时,应该正确处理", t, func() { - job := &mockTaskJob{status: task.TaskStatusFailed} +func TestRemovePool(t *testing.T) { + Convey("测试RemovePool函数", t, func() { + testPool := &task.TaskPool{} + testPool.Pool.PoolId = "test-pool" + allPools = map[string]*task.TaskPool{ + "test-pool": testPool, + } - patches := gomonkey.ApplyFunc(dealRunningJob, func(task.TaskJob, func(task.TaskJob)) { - panic("dealRunningJob exception") + Convey("移除空的池", func() { + patches := gomonkey.ApplyMethod(reflect.TypeOf(testPool), "GetRunningCount", func(*task.TaskPool) int { + return 0 + }) + patches.ApplyMethod(reflect.TypeOf(testPool), "GetWaitingCount", func(*task.TaskPool) int { + return 0 + }) + defer patches.Reset() + + err := RemovePool("test-pool") + So(err, ShouldBeNil) + So(allPools, ShouldNotContainKey, "test-pool") }) - defer patches.Reset() - So(func() { dealRunningJob(job) }, ShouldPanic) + Convey("移除有任务的池", func() { + patches := gomonkey.ApplyMethod(reflect.TypeOf(testPool), "GetRunningCount", func(*task.TaskPool) int { + return 1 + }) + patches.ApplyMethod(reflect.TypeOf(testPool), "GetWaitingCount", func(*task.TaskPool) int { + return 0 + }) + defer patches.Reset() - patches.ApplyFunc(resolveMetrics, func(*task.Metric) { - panic("resolveMetrics exception") + err := RemovePool("test-pool") + So(err, ShouldNotBeNil) }) - So(func() { dealRunningJob(job) }, ShouldPanic) + Convey("移除不存在的池", func() { + err := RemovePool("non-existent-pool") + So(err, ShouldBeNil) + }) }) } -// Test case 6: Process large number of jobs in short time to evaluate performance -func TestHandleRunningJob_Performance(t *testing.T) { - Convey("快速处理大量作业,并评估性能", t, func() { - job := &mockTaskJob{status: task.TaskStatusRunning} - tp := &task.TaskPool{} - numJobs := 1000 - sendFinishedChanCalledCount := 0 - gomonkey.ApplyFunc(tp.SendFinishedChan, func(task.TaskJob) { - sendFinishedChanCalledCount++ +func TestGetJob(t *testing.T) { + Convey("测试GetJob函数", t, func() { + testJob := &mockTaskJob{} + allJobs = map[string]task.TaskJob{ + "job1": testJob, + } + + Convey("获取存在的任务", func() { + job, err := GetJob("job1") + So(err, ShouldBeNil) + So(job, ShouldEqual, testJob) }) - for i := 0; i < numJobs; i++ { - dealRunningJob(job) - } + Convey("获取不存在的任务", func() { + patches := gomonkey.ApplyFunc(task.LoadJob, func(uuri string) (task.TaskJob, error) { + return nil, fmt.Errorf("not found") + }) + defer patches.Reset() - So(sendFinishedChanCalledCount, ShouldEqual, 0) - }) -} + job, err := GetJob("non-existent-job") + So(err, ShouldNotBeNil) + So(job, ShouldBeNil) + }) -// Test case 7: Verify behavior when sendFinishedChan is nil -func TestHandleRunningJob_NilSendFinishedChan(t *testing.T) { - Convey("当 sendFinishedChan 为 nil 时,应该正确处理", t, func() { - job := &mockTaskJob{status: task.TaskStatusSucceeded} + Convey("从数据库加载失败", func() { + patches := gomonkey.ApplyFunc(task.LoadJob, func(uuid string) (task.TaskJob, error) { + return nil, fmt.Errorf("load failed") + }) + defer patches.Reset() - So(func() { dealRunningJob(job) }, ShouldNotPanic) + job, err := GetJob("job2") + So(err, ShouldNotBeNil) + So(job, ShouldBeNil) + }) }) } -// Test case 8: Verify thread safety under concurrent calls -func TestHandleRunningJob_ConcurrentInvocations(t *testing.T) { - Convey("并发调用以确保线程安全", t, func() { - job := &mockTaskJob{status: task.TaskStatusRunning} - tp := &task.TaskPool{} - var jobs []task.TaskJob - for i := 0; i < 100; i++ { - jobs = append(jobs, job) +func TestPoolNewJob(t *testing.T) { + Convey("测试PoolNewJob函数", t, func() { + testTaskRec := &dao.TaskRec{ + TaskObjRec: dao.TaskObjRec{UUID: "test-task"}, } + testJob := &mockTaskJob{} + testPool := &task.TaskPool{} + testPool.Pool.PoolId = "test-pool" - gomonkey.ApplyFunc(tp.SendFinishedChan, func(task.TaskJob) {}) - - var wg sync.WaitGroup - for _, j := range jobs { - wg.Add(1) - go func(job task.TaskJob) { - defer wg.Done() - dealRunningJob(job) - }(j) + allPools = map[string]*task.TaskPool{ + "test-pool": testPool, } - wg.Wait() - }) -} -// Test case 9: Verify external system dependencies in dealRunningJob and resolveMetrics -func TestHandleRunningJob_ExternalDependencies(t *testing.T) { - Convey("验证函数对外部系统的依赖,例如数据库或网络调用", t, func() { - job := &mockTaskJob{status: task.TaskStatusRunning} + Convey("成功创建任务", func() { + patches := gomonkey.ApplyFunc(task.CreateJob, func(tr *dao.TaskRec) (task.TaskJob, error) { + return testJob, nil + }) + patches.ApplyFunc(selectPool, func(job task.TaskJob) (*task.TaskPool, error) { + return testPool, nil + }) + defer patches.Reset() - patches := gomonkey.ApplyFunc(dealRunningJob, func(task.TaskJob, func(task.TaskJob)) { - // Mock external system call + job, err := PoolNewJob(testTaskRec) + So(err, ShouldBeNil) + So(job, ShouldEqual, testJob) + So(allJobs, ShouldContainKey, "test-task") }) - defer patches.Reset() - patches.ApplyFunc(resolveMetrics, func(*task.Metric) { - // Mock external system call + Convey("创建任务失败", func() { + patches := gomonkey.ApplyFunc(task.CreateJob, func(tr *dao.TaskRec) (task.TaskJob, error) { + return nil, fmt.Errorf("create failed") + }) + defer patches.Reset() + + job, err := PoolNewJob(testTaskRec) + So(err, ShouldNotBeNil) + So(job, ShouldBeNil) }) - dealRunningJob(job) + Convey("选择池失败", func() { + patches := gomonkey.ApplyFunc(task.CreateJob, func(tr *dao.TaskRec) (task.TaskJob, error) { + return testJob, nil + }) + patches.ApplyFunc(selectPool, func(job task.TaskJob) (*task.TaskPool, error) { + return nil, fmt.Errorf("no suitable pool") + }) + defer patches.Reset() + + job, err := PoolNewJob(testTaskRec) + So(err, ShouldNotBeNil) + So(job, ShouldBeNil) + }) }) } -// Test case 10: Verify behavior when stopJob is called -func TestHandleRunningJob_StopJobCalled(t *testing.T) { - Convey("当需要停止作业时,应该正确调用 stopJob", t, func() { - job := &mockTaskJob{status: task.TaskStatusRunning} +func TestCancelJob(t *testing.T) { + Convey("测试CancelJob函数", t, func() { + testJob := &mockTaskJob{} + allJobs = map[string]task.TaskJob{ + "job1": testJob, + } - stopCalled := false - var calledStatus task.TaskStatus + Convey("取消存在的任务", func() { + patches := gomonkey.ApplyFunc(stopJob, func(job task.TaskJob, status task.TaskStatus, err error) { + // mock stopJob + }) + defer patches.Reset() - patches := gomonkey.ApplyFunc(stopJob, func(j task.TaskJob, status task.TaskStatus) { - stopCalled = true - calledStatus = status + err := CancelJob("job1") + So(err, ShouldBeNil) }) - defer patches.Reset() - // Mock job stopping scenario - patches.ApplyMethod(reflect.TypeOf(job), "GetStatus", func() task.TaskStatus { - return task.TaskStatusFailed + Convey("取消不存在的任务", func() { + patches := gomonkey.ApplyFunc(dao.ExistTask, func(uuid string) (bool, error) { + return false, nil + }) + defer patches.Reset() + + err := CancelJob("non-existent-job") + So(err, ShouldNotBeNil) }) - dealRunningJob(job) + Convey("检查任务存在性失败", func() { + patches := gomonkey.ApplyFunc(dao.ExistTask, func(uuid string) (bool, error) { + return false, fmt.Errorf("check failed") + }) + defer patches.Reset() - So(stopCalled, ShouldBeTrue) - So(calledStatus, ShouldEqual, task.TaskStatusFailed) + err := CancelJob("job2") + So(err, ShouldNotBeNil) + }) }) } diff --git a/internal/task/taskinstance_test.go b/internal/task/taskinstance_test.go index 0ee7220..5dadc65 100644 --- a/internal/task/taskinstance_test.go +++ b/internal/task/taskinstance_test.go @@ -8,12 +8,12 @@ import ( ) func TestTaskInstance_Compile(t *testing.T) { - bs2, err := os.ReadFile("testdata/template_train_standalone.yaml") + bs2, err := os.ReadFile("./testdata/template_train_standalone.yaml") if err != nil { panic(err) } - expectHcaYaml, err := os.ReadFile("./testdata/expect_hca_train.yaml") + expectHcaYaml, err := os.ReadFile("./testdata/expect_train_standalone.yaml") if err != nil { panic(err) } @@ -30,6 +30,7 @@ func TestTaskInstance_Compile(t *testing.T) { TaskRec: dao.TaskRec{ TaskRuntimeRec: dao.TaskRuntimeRec{}, TaskObjRec: dao.TaskObjRec{ + UUID: "uuid0", Namespace: "for-test-namespace", Name: "for-test-name", Pool: "h100-mem-2t", @@ -56,6 +57,7 @@ func TestTaskInstance_Compile(t *testing.T) { if strings.TrimSpace(got) != strings.TrimSpace(tt.want) { t.Errorf("TaskInstance.Compile() = %v, want %v", got, tt.want) } + os.Remove("out.yaml") }) } } diff --git a/internal/task/testdata/expect_hca_train.yaml b/internal/task/testdata/expect_hca_train.yaml index cc2b9a7..f8d3bf0 100644 --- a/internal/task/testdata/expect_hca_train.yaml +++ b/internal/task/testdata/expect_hca_train.yaml @@ -136,11 +136,11 @@ metadata: labels: project-id: "aip" rtx-user: "zhangzhaojin40458" - run-id: "0" + run-id: "uuid0" task-project: "aip" task-user: "zhangzhaojin40458" - task-run-id: "0" - task-id: "0" + task-run-id: "uuid0" + task-id: "uuid0" task-name: "for-test-name" task-uuid: "" taskd: taskd @@ -159,11 +159,11 @@ spec: labels: project-id: "aip" rtx-user: "zhangzhaojin40458" - run-id: "0" + run-id: "uuid0" task-project: "aip" task-user: "zhangzhaojin40458" - task-run-id: "0" - task-id: "0" + task-run-id: "uuid0" + task-id: "uuid0" task-name: "for-test-name" task-uuid: "" taskd: taskd @@ -255,11 +255,11 @@ spec: labels: project-id: "aip" rtx-user: "zhangzhaojin40458" - run-id: "0" + run-id: "uuid0" task-project: "aip" task-user: "zhangzhaojin40458" - task-run-id: "0" - task-id: "0" + task-run-id: "uuid0" + task-id: "uuid0" task-name: "for-test-name" task-uuid: "" taskd: taskd diff --git a/internal/task/testdata/expect_train_standalone.yaml b/internal/task/testdata/expect_train_standalone.yaml new file mode 100644 index 0000000..7204040 --- /dev/null +++ b/internal/task/testdata/expect_train_standalone.yaml @@ -0,0 +1,97 @@ +apiVersion: kubeflow.org/v1 +kind: PyTorchJob +metadata: + labels: + project-id: "aip" + rtx-user: "zhangzhaojin40458" + run-id: "uuid0" + task-project: "aip" + task-user: "zhangzhaojin40458" + task-run-id: "uuid0" + task-id: "uuid0" + task-name: "for-test-name" + task-uuid: "uuid0" + taskd: taskd + name: "for-test-name" + namespace: "for-test-namespace" +spec: + pytorchReplicaSpecs: + Master: + replicas: 1 + restartPolicy: Never + template: + metadata: + labels: + project-id: "aip" + rtx-user: "zhangzhaojin40458" + run-id: "uuid0" + task-project: "aip" + task-user: "zhangzhaojin40458" + task-run-id: "uuid0" + task-id: "uuid0" + task-name: "for-test-name" + task-uuid: "uuid0" + taskd: taskd + type: pytorchjob + annotations: + sidecar.istio.io/inject: "false" + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: aip.sangfor.com/pool + operator: In + values: + - h100-mem-2t + containers: + - command: + - /bin/bash + - -c + - echo $CONDA_DIR && source ${CONDA_DIR:-/opt/conda}/etc/profile.d/conda.sh && conda info --envs && conda activate /home/jovyan/work/zjz/env/zjz && sleep infinity + env: + - name: TRAINING_CONDA + value: "/home/jovyan/work/zjz/env/zjz" + name: pytorch + image: registry.ai.sangfor.com/ai-sangfor/code-studio:torch-2.1-cu121-v1.0.0 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 112 + memory: 983040Mi + nvidia.com/gpu: 8 + limits: + cpu: 112 + memory: 983040Mi + nvidia.com/gpu: 8 + volumeMounts: + - mountPath: /home/jovyan + name: pvc-8dd98f6a-c30f-4d59-a017-23e60309b06f + - mountPath: /mnt/project/aip + name: hostpath-fd621f42-d0d0-4fe6-98e1-bf6b41252e33 + - mountPath: /etc/localtime + name: tz-config + - mountPath: /dev/shm + name: dshm + workingDir: /home/jovyan/ + restartPolicy: Never + schedulerName: gpu-scheduler-plugins + volumes: + - name: pvc-8dd98f6a-c30f-4d59-a017-23e60309b06f + persistentVolumeClaim: + claimName: dfdfd + - name: hostpath-fd621f42-d0d0-4fe6-98e1-bf6b41252e33 + hostPath: + path: /mnt/project/aip + type: DirectoryOrCreate + - hostPath: + path: /usr/share/zoneinfo/Asia/Shanghai + name: tz-config + - emptyDir: + medium: Memory + name: dshm + runPolicy: + backoffLimit: 0 + + diff --git a/internal/task/testdata/template_train_standalone.yaml b/internal/task/testdata/template_train_standalone.yaml index 916a2da..7fea832 100644 --- a/internal/task/testdata/template_train_standalone.yaml +++ b/internal/task/testdata/template_train_standalone.yaml @@ -4,11 +4,11 @@ metadata: labels: project-id: "{{._extra.projectName}}" rtx-user: "{{._extra.ownerName}}" - run-id: "{{._instance.ID}}" + run-id: "{{._task.UUID}}" task-project: "{{._extra.projectName}}" task-user: "{{._extra.ownerName}}" - task-run-id: "{{._instance.ID}}" - task-id: "{{._task.ID}}" + task-run-id: "{{._task.UUID}}" + task-id: "{{._task.UUID}}" task-name: "{{._task.Name}}" task-uuid: "{{._task.UUID}}" taskd: taskd @@ -24,11 +24,11 @@ spec: labels: project-id: "{{._extra.projectName}}" rtx-user: "{{._extra.ownerName}}" - run-id: "{{._instance.ID}}" + run-id: "{{._task.UUID}}" task-project: "{{._extra.projectName}}" task-user: "{{._extra.ownerName}}" - task-run-id: "{{._instance.ID}}" - task-id: "{{._task.ID}}" + task-run-id: "{{._task.UUID}}" + task-id: "{{._task.UUID}}" task-name: "{{._task.Name}}" task-uuid: "{{._task.UUID}}" taskd: taskd @@ -44,7 +44,7 @@ spec: - key: aip.sangfor.com/pool operator: In values: - - {{yamlValue ._instance.Pool "a800-pcie"}} + - {{yamlValue ._task.Pool "a800-pcie"}} containers: - command: - /bin/bash diff --git a/main.go b/main.go index 9268bbf..5fba010 100644 --- a/main.go +++ b/main.go @@ -148,30 +148,33 @@ func runHttpServer(c *utils.ServerConfig) { // Register Swagger handler r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) - // Tasks - r.POST("/taskd/api/v1/tasks", controllers.TaskCommit) - r.GET("/taskd/api/v1/tasks", controllers.ListTasks) - r.GET("/taskd/api/v1/tasks/:uuid", controllers.TaskData) - r.GET("/taskd/api/v1/tasks/:uuid/status", controllers.TaskStatus) - r.GET("/taskd/api/v1/tasks/:uuid/logs", controllers.TaskLogs) - r.GET("/taskd/api/v1/tasks/:uuid/tags", controllers.TaskGetTags) - r.POST("/taskd/api/v1/tasks/:uuid/tags", controllers.TaskTags) - r.DELETE("/taskd/api/v1/tasks/:uuid", controllers.TaskStop) - - // Task templates - r.POST("/taskd/api/v1/templates", controllers.AddTemplate) - r.PUT("/taskd/api/v1/templates/:name", controllers.UpdateTemplate) - r.GET("/taskd/api/v1/templates", controllers.ListTemplates) - r.GET("/taskd/api/v1/templates/:name", controllers.GetTemplate) - r.DELETE("/taskd/api/v1/templates/:name", controllers.DeleteTemplate) - - // Task pools - r.POST("/taskd/api/v1/pools", controllers.AddPool) - r.GET("/taskd/api/v1/pools", controllers.ListPools) - r.GET("/taskd/api/v1/pools/:name", controllers.GetPool) - r.PUT("/taskd/api/v1/pools/:name", controllers.UpdatePool) - r.DELETE("/taskd/api/v1/pools/:name", controllers.DeletePool) + apiv1 := r.Group("/taskd/api/v1") + { + // Tasks + apiv1.POST("/tasks", controllers.TaskCommit) + apiv1.GET("/tasks", controllers.ListTasks) + apiv1.GET("/tasks/:uuid", controllers.TaskData) + apiv1.GET("/tasks/:uuid/status", controllers.TaskStatus) + apiv1.GET("/tasks/:uuid/logs", controllers.TaskLogs) + apiv1.GET("/tasks/:uuid/tags", controllers.TaskGetTags) + apiv1.POST("/tasks/:uuid/tags", controllers.TaskTags) + apiv1.DELETE("/tasks/:uuid", controllers.TaskStop) + + // Task templates + apiv1.POST("/templates", controllers.AddTemplate) + apiv1.PUT("/templates/:name", controllers.UpdateTemplate) + apiv1.GET("/templates", controllers.ListTemplates) + apiv1.GET("/templates/:name", controllers.GetTemplate) + apiv1.DELETE("/templates/:name", controllers.DeleteTemplate) + + // Task pools + apiv1.POST("/pools", controllers.AddPool) + apiv1.GET("/pools", controllers.ListPools) + apiv1.GET("/pools/:name", controllers.GetPool) + apiv1.PUT("/pools/:name", controllers.UpdatePool) + apiv1.DELETE("/pools/:name", controllers.DeletePool) + } err := r.Run(c.ListenAddr) if err != nil { log.Fatal(err) diff --git a/makefile b/makefile index d9daefe..74922af 100644 --- a/makefile +++ b/makefile @@ -8,8 +8,11 @@ VER := 1.0.250604 OS := $(shell go env GOOS) ARCH := $(shell go env GOARCH) ENV := test -DOCKER_REPO := docker.sangfor.com/cicd_2740 -DOCKER_TAG := $(APP):$(VER) +SHENMA_DOCKER_REPO := $(shell grep '^SHENMA_DOCKER_REPO=' ./.env | cut -d '=' -f 2-) +SHENMA_DOCKER_HOST := $(shell grep '^SHENMA_DOCKER_HOST=' ./.env | cut -d '=' -f 2-) +SHENMA_DOCKER_USER := $(shell grep '^SHENMA_DOCKER_USER=' ./.env | cut -d '=' -f 2-) +SHENMA_DOCKER_PASSWORD := $(shell grep '^SHENMA_DOCKER_PASSWORD=' ./.env | cut -d '=' -f 2-) +UPLOAD_GITHUB := "../upload-docker-images" #ENV := prod EXEEXT ?= @@ -35,27 +38,38 @@ package: # 上传镜像包到dockerhub upload_dockerhub: - docker tag $(APP):$(VER) $(DOCKER_REPO)/$(APP):$(VER) - docker login $(DOCKER_HOST) -u $(DOCKER_USER) -p $(DOCKER_PASSWORD) - docker push $(DOCKER_REPO)/$(APP):$(VER) + docker tag $(APP):$(VER) $(SHENMA_DOCKER_REPO)/$(APP):$(VER) + docker login $(SHENMA_DOCKER_HOST) -u $(SHENMA_DOCKER_USER) -p $(SHENMA_DOCKER_PASSWORD) + docker push $(SHENMA_DOCKER_REPO)/$(APP):$(VER) + +upload_github: + docker tag $(APP):$(VER) zgsm/$(APP):$(VER) + docker save -o $(APP)-$(VER).tar zgsm/$(APP):$(VER) + mv $(APP)-$(VER).tar $(UPLOAD_GITHUB)/images/ + @echo -------TODO: upload image to dockerhub------- + @echo cd $(UPLOAD_GITHUB) + @echo git add images/$(APP)-$(VER).tar + @echo git commit -am \"upload zgsm/$(APP):$(VER)\" + @echo git push origin main # 上传镜像包到制品库和前置harbor upload: upload_dockerhub +DEPLOY_YAML := "./__$(APP)_$(ENV)_$(VER).yaml" # 生成服务部署的YAML配置 -genyaml: - shenma-secret.sh -d $(APP) -p $(ENV) -v $(VER) -t ./$(APP).template.yaml +genyaml: + echo generate $(DEPLOY_YAML) ... + bash shenma-secret.sh -d $(APP) -p $(ENV) -v $(VER) -t ./$(APP).template.yaml -# 应用生成的配置 apply: - kubectl delete -f ./__$(APP)_$(ENV)_$(VER).yaml - kubectl apply -f ./__$(APP)_$(ENV)_$(VER).yaml + kubectl delete -f $(DEPLOY_YAML) + kubectl apply -f $(DEPLOY_YAML) k8s_clean: - kubectl delete -f ./__$(APP)_$(ENV)_$(VER).yaml + kubectl delete -f $(DEPLOY_YAML) k8s_create: - kubectl apply -f ./__$(APP)_$(ENV)_$(VER).yaml + kubectl apply -f $(DEPLOY_YAML) # 部署 deploy: package upload genyaml apply diff --git a/taskd.template.yaml b/taskd.template.yaml index 7e9f27e..262b4f1 100644 --- a/taskd.template.yaml +++ b/taskd.template.yaml @@ -13,6 +13,10 @@ data: port: ${{__env_profile.database.port}} password: ${{__env_profile.database.password}} user: ${{__env_profile.database.user}} + redis: + addr: ${{__env_profile.redis.addr}} + password: ${{__env_profile.redis.password}} + db: ${{__env_profile.redis.db}} timeout: phaseQueueDefault: 300 phaseInitDefault: 300