From 940cdfc0e756ae963b5048ab703c7cd4d325a3d4 Mon Sep 17 00:00:00 2001 From: luziqi Date: Tue, 18 Oct 2022 16:06:35 +0800 Subject: [PATCH] update --- docs/docs.go | 326 +++++++++++++++++++++++++++++++++++++- docs/swagger.json | 326 +++++++++++++++++++++++++++++++++++++- docs/swagger.yaml | 215 ++++++++++++++++++++++++- global/model.go | 10 ++ main.go | 10 ++ models/monkey_activity.go | 14 ++ models/monkey_device.go | 26 +++ models/monkey_pid.go | 13 ++ models/monkey_result.go | 19 +++ models/monkey_task.go | 30 ++-- monkey/activity.go | 84 ++++++++++ monkey/base.go | 54 +++++++ monkey/cli.go | 33 ---- monkey/cli_adr.go | 124 +++++++++++++++ monkey/device.go | 31 ++++ monkey/result.go | 96 +++++++++++ monkey/task.go | 238 +++++++++++++++++++++++++++- test/test.go | 21 +++ 18 files changed, 1617 insertions(+), 53 deletions(-) create mode 100644 global/model.go create mode 100644 models/monkey_activity.go create mode 100644 models/monkey_device.go create mode 100644 models/monkey_pid.go create mode 100644 models/monkey_result.go create mode 100644 monkey/activity.go create mode 100644 monkey/base.go delete mode 100644 monkey/cli.go create mode 100644 monkey/cli_adr.go create mode 100644 monkey/device.go create mode 100644 monkey/result.go create mode 100644 test/test.go diff --git a/docs/docs.go b/docs/docs.go index 12f0508..007ea5a 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -101,6 +101,281 @@ var doc = `{ } } }, + "/api/monkey/v1/devices": { + "get": { + "description": "获取安卓设备列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "获取设备列表", + "parameters": [ + { + "type": "integer", + "description": "平台:ios/adr", + "name": "platform", + "in": "query" + } + ], + "responses": { + "200": { + "description": "返回设备信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task": { + "get": { + "description": "根据id获取monkey任务信息", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "获取monkey任务信息", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "返回monkey任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task/activity": { + "get": { + "description": "通过monkey任务id获取覆盖的活动页面", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "获取覆盖页面列表", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "返回任务覆盖的活动页", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + }, + "post": { + "description": "Android上报activity名", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "上报Monkey应用页", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "设备id", + "name": "device_name", + "in": "formData" + }, + { + "type": "string", + "description": "页面名称", + "name": "activity_name", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "返回更新后的任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task/crash_count": { + "post": { + "description": "更新Monkey任务崩溃数量", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "更新Monkey任务崩溃数量", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "要更新的崩溃数量", + "name": "crash_count", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "返回更新后的任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task/pid": { + "post": { + "description": "上传进程id并关联到任务", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "上报进程id", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "进程id", + "name": "pid", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "返回成功或失败", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task/result": { + "get": { + "description": "通过任务id获取Monkey结果", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "获取Monkey结果", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "返回任务结果", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + }, + "post": { + "description": "上报Monkey结果", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "上报Monkey结果", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "crash_log_list", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "activity_name_info", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "device_name", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "status", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "返回更新后的任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/monkey/v1/task/status": { "post": { "description": "更新Monkey任务状态,进行中为RUNNING,已完成为FINIASHED,如有错误为ERROR", @@ -114,7 +389,7 @@ var doc = `{ "parameters": [ { "type": "integer", - "description": "项目名", + "description": "任务id", "name": "task_id", "in": "formData", "required": true @@ -136,6 +411,35 @@ var doc = `{ } } }, + "/api/monkey/v1/task/stop": { + "post": { + "description": "停止monkey任务,杀死所有关联任务的进程id", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "停止monkey任务", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "返回成功或失败", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/monkey/v1/tasks": { "get": { "description": "获取任务列表", @@ -169,6 +473,26 @@ var doc = `{ } } } + }, + "/webdav/monkey/task/:id/:filename": { + "put": { + "description": "上传Logcat日志", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "上传Logcat日志", + "responses": { + "200": { + "description": "返回成功或失败", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } } }, "definitions": { diff --git a/docs/swagger.json b/docs/swagger.json index a85e5d6..bfac20b 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -82,6 +82,281 @@ } } }, + "/api/monkey/v1/devices": { + "get": { + "description": "获取安卓设备列表", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "获取设备列表", + "parameters": [ + { + "type": "integer", + "description": "平台:ios/adr", + "name": "platform", + "in": "query" + } + ], + "responses": { + "200": { + "description": "返回设备信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task": { + "get": { + "description": "根据id获取monkey任务信息", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "获取monkey任务信息", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "返回monkey任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task/activity": { + "get": { + "description": "通过monkey任务id获取覆盖的活动页面", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "获取覆盖页面列表", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "返回任务覆盖的活动页", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + }, + "post": { + "description": "Android上报activity名", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "上报Monkey应用页", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "设备id", + "name": "device_name", + "in": "formData" + }, + { + "type": "string", + "description": "页面名称", + "name": "activity_name", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "返回更新后的任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task/crash_count": { + "post": { + "description": "更新Monkey任务崩溃数量", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "更新Monkey任务崩溃数量", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "要更新的崩溃数量", + "name": "crash_count", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "返回更新后的任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task/pid": { + "post": { + "description": "上传进程id并关联到任务", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "上报进程id", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "进程id", + "name": "pid", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "返回成功或失败", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, + "/api/monkey/v1/task/result": { + "get": { + "description": "通过任务id获取Monkey结果", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "获取Monkey结果", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "返回任务结果", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + }, + "post": { + "description": "上报Monkey结果", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "上报Monkey结果", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "crash_log_list", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "activity_name_info", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "device_name", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "status", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "返回更新后的任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/monkey/v1/task/status": { "post": { "description": "更新Monkey任务状态,进行中为RUNNING,已完成为FINIASHED,如有错误为ERROR", @@ -95,7 +370,7 @@ "parameters": [ { "type": "integer", - "description": "项目名", + "description": "任务id", "name": "task_id", "in": "formData", "required": true @@ -117,6 +392,35 @@ } } }, + "/api/monkey/v1/task/stop": { + "post": { + "description": "停止monkey任务,杀死所有关联任务的进程id", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "停止monkey任务", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "返回成功或失败", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/monkey/v1/tasks": { "get": { "description": "获取任务列表", @@ -150,6 +454,26 @@ } } } + }, + "/webdav/monkey/task/:id/:filename": { + "put": { + "description": "上传Logcat日志", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v1/" + ], + "summary": "上传Logcat日志", + "responses": { + "200": { + "description": "返回成功或失败", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } } }, "definitions": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index d0ddd9f..c8f87ae 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -62,13 +62,194 @@ paths: summary: 新建Monkey任务 tags: - Monkey相关 /api/monkey/v1/ + /api/monkey/v1/devices: + get: + consumes: + - application/x-www-form-urlencoded + description: 获取安卓设备列表 + parameters: + - description: 平台:ios/adr + in: query + name: platform + type: integer + responses: + "200": + description: 返回设备信息 + schema: + $ref: '#/definitions/models.Response' + summary: 获取设备列表 + tags: + - Monkey相关 /api/monkey/v1/ + /api/monkey/v1/task: + get: + consumes: + - application/x-www-form-urlencoded + description: 根据id获取monkey任务信息 + parameters: + - description: 任务id + in: query + name: id + type: integer + responses: + "200": + description: 返回monkey任务信息 + schema: + $ref: '#/definitions/models.Response' + summary: 获取monkey任务信息 + tags: + - Monkey相关 /api/monkey/v1/ + /api/monkey/v1/task/activity: + get: + consumes: + - application/x-www-form-urlencoded + description: 通过monkey任务id获取覆盖的活动页面 + parameters: + - description: 任务id + in: query + name: task_id + required: true + type: integer + responses: + "200": + description: 返回任务覆盖的活动页 + schema: + $ref: '#/definitions/models.Response' + summary: 获取覆盖页面列表 + tags: + - Monkey相关 /api/monkey/v1/ + post: + consumes: + - application/x-www-form-urlencoded + description: Android上报activity名 + parameters: + - description: 任务id + in: formData + name: task_id + required: true + type: integer + - description: 设备id + in: formData + name: device_name + type: string + - description: 页面名称 + in: formData + name: activity_name + type: string + responses: + "200": + description: 返回更新后的任务信息 + schema: + $ref: '#/definitions/models.Response' + summary: 上报Monkey应用页 + tags: + - Monkey相关 /api/monkey/v1/ + /api/monkey/v1/task/crash_count: + post: + consumes: + - application/x-www-form-urlencoded + description: 更新Monkey任务崩溃数量 + parameters: + - description: 任务id + in: formData + name: task_id + required: true + type: integer + - description: 要更新的崩溃数量 + in: formData + name: crash_count + type: string + responses: + "200": + description: 返回更新后的任务信息 + schema: + $ref: '#/definitions/models.Response' + summary: 更新Monkey任务崩溃数量 + tags: + - Monkey相关 /api/monkey/v1/ + /api/monkey/v1/task/pid: + post: + consumes: + - application/x-www-form-urlencoded + description: 上传进程id并关联到任务 + parameters: + - description: 任务id + in: formData + name: task_id + required: true + type: integer + - description: 进程id + in: formData + name: pid + required: true + type: integer + responses: + "200": + description: 返回成功或失败 + schema: + $ref: '#/definitions/models.Response' + summary: 上报进程id + tags: + - Monkey相关 /api/monkey/v1/ + /api/monkey/v1/task/result: + get: + consumes: + - application/x-www-form-urlencoded + description: 通过任务id获取Monkey结果 + parameters: + - description: 任务id + in: query + name: task_id + required: true + type: integer + responses: + "200": + description: 返回任务结果 + schema: + $ref: '#/definitions/models.Response' + summary: 获取Monkey结果 + tags: + - Monkey相关 /api/monkey/v1/ + post: + consumes: + - application/x-www-form-urlencoded + description: 上报Monkey结果 + parameters: + - description: 任务id + in: formData + name: task_id + required: true + type: integer + - description: 要更新的任务状态 + in: formData + name: crash_log_list + type: string + - description: 要更新的任务状态 + in: formData + name: activity_name_info + type: string + - description: 要更新的任务状态 + in: formData + name: device_name + type: string + - description: 要更新的任务状态 + in: formData + name: status + type: string + responses: + "200": + description: 返回更新后的任务信息 + schema: + $ref: '#/definitions/models.Response' + summary: 上报Monkey结果 + tags: + - Monkey相关 /api/monkey/v1/ /api/monkey/v1/task/status: post: consumes: - application/x-www-form-urlencoded description: 更新Monkey任务状态,进行中为RUNNING,已完成为FINIASHED,如有错误为ERROR parameters: - - description: 项目名 + - description: 任务id in: formData name: task_id required: true @@ -85,6 +266,25 @@ paths: summary: 更新Monkey任务状态 tags: - Monkey相关 /api/monkey/v1/ + /api/monkey/v1/task/stop: + post: + consumes: + - application/x-www-form-urlencoded + description: 停止monkey任务,杀死所有关联任务的进程id + parameters: + - description: 任务id + in: formData + name: task_id + required: true + type: integer + responses: + "200": + description: 返回成功或失败 + schema: + $ref: '#/definitions/models.Response' + summary: 停止monkey任务 + tags: + - Monkey相关 /api/monkey/v1/ /api/monkey/v1/tasks: get: consumes: @@ -107,4 +307,17 @@ paths: summary: 获取任务列表 tags: - Monkey相关 /api/monkey/v1/ + /webdav/monkey/task/:id/:filename: + put: + consumes: + - application/x-www-form-urlencoded + description: 上传Logcat日志 + responses: + "200": + description: 返回成功或失败 + schema: + $ref: '#/definitions/models.Response' + summary: 上传Logcat日志 + tags: + - Monkey相关 /api/monkey/v1/ swagger: "2.0" diff --git a/global/model.go b/global/model.go new file mode 100644 index 0000000..609bd2b --- /dev/null +++ b/global/model.go @@ -0,0 +1,10 @@ +package global + +import "time" + +type MODEL struct { + ID uint `json:"id" gorm:"column:id;type:int(11);primary_key;not null;autoIncrement;comment:主键"` + CreateTime time.Time `json:"create_time" gorm:"column:create_time;type:int(11);not null;autoCreateTime;comment:创建时间"` + UpdateTime time.Time `json:"update_time" gorm:"column:update_time;type:int(11);not null;autoUpdateTime;comment:更新时间"` + IsDel int `json:"-" gorm:"column:is_del;type:int(1);not null;comment:是否已删除"` +} diff --git a/main.go b/main.go index d1ba716..723693a 100644 --- a/main.go +++ b/main.go @@ -56,7 +56,17 @@ func main() { // monkey r.POST("/api/monkey/v1/create_task", monkey.CreateTask) r.POST("/api/monkey/v1/task/status", monkey.UpdateTaskStatus) + r.POST("/api/monkey/v1/task/result", monkey.UploadMonkeyResult) + r.POST("/api/monkey/v1/task/stop", monkey.StopMonkeyTask) + r.POST("/api/monkey/v1/task/pid", monkey.UpdatePids) + r.GET("/api/monkey/v1/task/result", monkey.GetMonkeyResult) + r.POST("/api/monkey/v1/task/activity", monkey.UpdataActivity) + r.GET("/api/monkey/v1/task/activity", monkey.GetMonkeyActivities) r.GET("/api/monkey/v1/tasks", monkey.GetTasks) + r.GET("/api/monkey/v1/task", monkey.GetTaskById) + r.GET("/api/monkey/v1/devices", monkey.GetDevices) + r.POST("/api/monkey/v1/task/crash_count", monkey.UpdateTaskCrashCount) + r.PUT("/webdav/monkey/task/:id/:filename", monkey.TaskReport) r.Run(port) diff --git a/models/monkey_activity.go b/models/monkey_activity.go new file mode 100644 index 0000000..d2bf939 --- /dev/null +++ b/models/monkey_activity.go @@ -0,0 +1,14 @@ +package models + +import "goqs/global" + +type MonkeyActivity struct { + global.MODEL + TaskId int `json:"task_id"` + DeviceName string `json:"device_name"` + ActivityName string `json:"activity_name"` +} + +func (m *MonkeyActivity) TableName() string { + return "monkey_activity" +} diff --git a/models/monkey_device.go b/models/monkey_device.go new file mode 100644 index 0000000..402dbc6 --- /dev/null +++ b/models/monkey_device.go @@ -0,0 +1,26 @@ +package models + +import "goqs/global" + +type Device struct { + global.MODEL + Project string `json:"project"` + ProductName string `json:"product_name" gorm:"product_name"` + Udid string `json:"udid" gorm:"udid"` + Status string `json:"status" gorm:"status"` + Platform string `json:"platform" gorm:"platform"` +} + +func (d *Device) TableName() string { + return "device" +} + +type MonkeyDevice struct { + // global.MODEL + // Project string `json:"project"` + // AppName string `json:"app_name" gorm:"app_name"` + Udid string `json:"udid" gorm:"udid"` + Status string `json:"status" gorm:"status"` + Platform string `json:"platform" gorm:"platform"` + ProductName string `json:"product_name" gorm:"product_name"` +} diff --git a/models/monkey_pid.go b/models/monkey_pid.go new file mode 100644 index 0000000..0a32629 --- /dev/null +++ b/models/monkey_pid.go @@ -0,0 +1,13 @@ +package models + +import "goqs/global" + +type MonkeyPid struct { + global.MODEL + TaskId int `json:"task_id" column:"task_id"` + PId int `json:"pid" gorm:"column:pid"` +} + +func (m *MonkeyPid) TableName() string { + return "monkey_pid" +} diff --git a/models/monkey_result.go b/models/monkey_result.go new file mode 100644 index 0000000..1990332 --- /dev/null +++ b/models/monkey_result.go @@ -0,0 +1,19 @@ +package models + +import "goqs/global" + +type MonkeyResult struct { + global.MODEL + TaskId int `json:"task_id"` + CrashLogs string `json:"-"` + CrashLogList []string `json:"crash_log_list" gorm:"-"` + ActivityNameInfo string `json:"-"` + ActivityList []string `json:"activity_list" gorm:"-"` + DeviceName string `json:"device_name"` + Logs string `json:"-"` + LogList []string `json:"log_list" gorm:"-"` +} + +func (m *MonkeyResult) TableName() string { + return "monkey_result" +} diff --git a/models/monkey_task.go b/models/monkey_task.go index 89d821b..9199f39 100644 --- a/models/monkey_task.go +++ b/models/monkey_task.go @@ -1,20 +1,22 @@ package models type MonkeyTask struct { - Id int `json:"id" gorm:"column:id;type:int(11);primary_key;not null;autoIncrement;comment:主键"` - Project string `json:"project" gorm:"column:project;type:varchar(255);not null;comment:项目名"` - PackageURL string `json:"package_url" gorm:"column:package_url;type:varchar(255);not null;comment:应用包下载链接"` - PackageName string `json:"package_name" gorm:"column:package_name;type:varchar(255);not null;comment:应用包名"` - LaunchActivity string `json:"launch_activity" gorm:"column:launch_activity;type:varchar(255);comment:启动Activity页"` - DeviceAmount int `json:"device_amount" gorm:"column:device_amount;type:int(11);not null;comment:运行设备数"` - RunTime int `json:"run_time" gorm:"column:run_time;type:int(11);not null;comment:运行时间(秒)"` - Platform string `json:"platform" gorm:"column:platform;type:varchar(255);comment:平台adr/ios"` - CrashCount int `json:"crash_count" gorm:"column:crash_count;type:int(11);not null;comment:崩溃次数"` - Creator string `json:"creator" gorm:"column:creator;type:varchar(255);comment:创建人"` - Status string `json:"status" gorm:"column:status;type:varchar(255);not null;comment:运行状态"` - CreateTime int `json:"create_time" gorm:"column:create_time;type:int(11);not null;autoCreateTime;comment:创建时间"` - UpdateTime int `json:"update_time" gorm:"column:update_time;type:int(11);not null;autoUpdateTime;comment:更新时间"` - IsDel int `json:"is_del" gorm:"column:is_del;type:int(1);not null;comment:是否已删除"` + Id int `json:"id" gorm:"column:id;type:int(11);primary_key;not null;autoIncrement;comment:主键"` + Project string `json:"project" gorm:"column:project;type:varchar(255);not null;comment:项目名"` + PackageURL string `json:"package_url" gorm:"column:package_url;type:varchar(255);not null;comment:应用包下载链接"` + PackageName string `json:"package_name" gorm:"column:package_name;type:varchar(255);not null;comment:应用包名"` + LaunchActivity string `json:"launch_activity" gorm:"column:launch_activity;type:varchar(255);comment:启动Activity页"` + DeviceAmount int `json:"device_amount" gorm:"column:device_amount;type:int(11);not null;comment:运行设备数"` + RunTime int `json:"run_time" gorm:"column:run_time;type:int(11);not null;comment:运行时间(秒)"` + RunPids string `json:"run_pids" gorm:"column:run_pids;type:varchar(255);comment:数组形式存放运行进程pid"` + Platform string `json:"platform" gorm:"column:platform;type:varchar(255);comment:平台adr/ios"` + CoveredAcitvities int `json:"covered_activities" gorm:"-"` + CrashCount int `json:"crash_count" gorm:"column:crash_count;type:int(11);not null;comment:崩溃次数"` + Creator string `json:"creator" gorm:"column:creator;type:varchar(255);comment:创建人"` + Status string `json:"status" gorm:"column:status;type:varchar(255);not null;comment:运行状态"` + CreateTime int `json:"create_time" gorm:"column:create_time;type:int(11);not null;autoCreateTime;comment:创建时间"` + UpdateTime int `json:"update_time" gorm:"column:update_time;type:int(11);not null;autoUpdateTime;comment:更新时间"` + IsDel int `json:"is_del" gorm:"column:is_del;type:int(1);not null;comment:是否已删除"` } func (m *MonkeyTask) TableName() string { diff --git a/monkey/activity.go b/monkey/activity.go new file mode 100644 index 0000000..b454ab6 --- /dev/null +++ b/monkey/activity.go @@ -0,0 +1,84 @@ +package monkey + +import ( + "goqs/controllers" + "goqs/dbsql" + "goqs/models" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/spf13/cast" +) + +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 上报Monkey应用页 +// @Description Android上报activity名 +// @accept x-www-form-urlencoded +// @Param task_id formData int true "任务id" +// @Param device_name formData string false "设备id" +// @Param activity_name formData string false "页面名称" +// @Success 200 {object} models.Response "返回更新后的任务信息" +// @Router /api/monkey/v1/task/activity [post] +func UpdataActivity(c *gin.Context) { + rsp := controllers.NewResponse() + + var res models.MonkeyActivity + res.TaskId = cast.ToInt(c.PostForm("task_id")) + if res.TaskId < 1 { + rsp.Error("task_id error:" + c.PostForm("task_id")) + c.JSON(http.StatusOK, rsp) + } + res.DeviceName = c.PostForm("device_name") + if res.DeviceName == "" { + rsp.Error("device_name不能为空") + c.JSON(http.StatusOK, rsp) + } + res.ActivityName = c.PostForm("activity_name") + if res.ActivityName == "" { + rsp.Error("activity_name不能为空") + c.JSON(http.StatusOK, rsp) + } + + db, err := dbsql.GetConn(dbsql.DSN) + if err != nil { + rsp.Error(err.Error()) + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + db.Create(&res) + if res.ID < 1 { + rsp.Error("记录activity应用页失败") + c.JSON(http.StatusOK, rsp) + return + } + + rsp.Success() + rsp.Data = res + c.JSON(http.StatusOK, rsp) +} + +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 获取覆盖页面列表 +// @Description 通过monkey任务id获取覆盖的活动页面 +// @accept x-www-form-urlencoded +// @Param task_id query int true "任务id" +// @Success 200 {object} models.Response "返回任务覆盖的活动页" +// @Router /api/monkey/v1/task/activity [get] +func GetMonkeyActivities(c *gin.Context) { + rsp := controllers.NewResponse() + + var list []models.MonkeyActivity + db, err := dbsql.GetConn(dbsql.DSN) + if err != nil { + rsp.Error(err.Error()) + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + db.Where("task_id = ?", c.Query("task_id")).Find(&list) + + rsp.Success() + rsp.Data = list + c.JSON(http.StatusOK, rsp) +} diff --git a/monkey/base.go b/monkey/base.go new file mode 100644 index 0000000..d1a086e --- /dev/null +++ b/monkey/base.go @@ -0,0 +1,54 @@ +package monkey + +import ( + "bufio" + "errors" + "os" +) + +func HasDir(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func CreateDir(path string) error { + exist, err := HasDir(path) + if err != nil { + return err + } + if exist { + return errors.New("文件夹已存在") + } else { + err := os.Mkdir(path, os.ModePerm) + if err != nil { + return err + } else { + return nil + } + } +} + +func CreateAndWriteFile(file_path string, data []byte) error { + file, err := os.OpenFile(file_path, os.O_WRONLY|os.O_CREATE, 0755) + if err != nil { + return err + } + defer file.Close() + + write := bufio.NewWriter(file) + _, err = write.Write(data) + if err != nil { + return err + } + err = write.Flush() + if err != nil { + return err + } + return nil +} diff --git a/monkey/cli.go b/monkey/cli.go deleted file mode 100644 index 90a9930..0000000 --- a/monkey/cli.go +++ /dev/null @@ -1,33 +0,0 @@ -package monkey - -import ( - "goqs/models" - "os/exec" - "time" - - log "github.com/sirupsen/logrus" - "github.com/spf13/cast" -) - -func runAndroidMonkeyCmd(task models.MonkeyTask) { - pkg_path := "/home/tmp/pkg/" + cast.ToString(time.Now().Unix()) + ".apk" - log.Debug("正在下载apk:", task.PackageURL) - err := exec.Command("wget", task.PackageURL, "-O", pkg_path).Run() - if err != nil { - log.Error(err) - } - log.Debug("下载完毕,开始调用monkey服务,安装包路径", pkg_path) - cmd_content := "cd /home/app/aimonkey && python3 main_run.py" + - " -task_id " + cast.ToString(task.Id) + - " -pkg_path " + pkg_path + - " -package " + task.PackageName + - " -activity " + task.LaunchActivity + - " -count " + cast.ToString(task.DeviceAmount) + - " -time " + cast.ToString(task.RunTime) - log.Debug(cmd_content) - cmd := exec.Command("bash", "-c", cmd_content) - err = cmd.Run() - if err != nil { - log.Error(err) - } -} diff --git a/monkey/cli_adr.go b/monkey/cli_adr.go new file mode 100644 index 0000000..b2fcd0f --- /dev/null +++ b/monkey/cli_adr.go @@ -0,0 +1,124 @@ +package monkey + +import ( + "fmt" + "goqs/models" + "os/exec" + "strings" + "time" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cast" +) + +func runAndroidMonkeyCmd(task models.MonkeyTask) { + + cmd_content := "cd /home/app/aimonkey && nohup python3 main_run.py" + + " -task_id " + cast.ToString(task.Id) + if task.PackageURL != "" { + pkg_path := "/home/tmp/pkg/" + cast.ToString(time.Now().Unix()) + ".apk" + log.Debug("正在下载apk:", task.PackageURL) + err := exec.Command("wget", task.PackageURL, "-O", pkg_path).Run() + if err != nil { + log.Error(err) + } + cmd_content += " -pkg_path " + pkg_path + log.Debug("下载完毕,安装包路径", pkg_path) + } + cmd_content += " -package " + task.PackageName + + " -activity " + task.LaunchActivity + + " -count " + cast.ToString(task.DeviceAmount) + + " -time " + cast.ToString(task.RunTime) + + " >> /home/app/logs/task_output/task_" + cast.ToString(task.Id) + ".log 2>&1" + + log.Debug("开始调用monkey服务") + log.Debug(cmd_content) + cmd := exec.Command("bash", "-c", cmd_content) + err := cmd.Run() + if err != nil { + log.Error(err) + } +} + +func GetAndroidDevices() map[string]string { + udid_map := make(map[string]string) + cmd := exec.Command("adb", "devices") + out, err := cmd.CombinedOutput() + if err != nil { + fmt.Println(err) + } + list := strings.Split(string(out), "\n")[1:] + for _, v := range list { + if len(v) < 1 { + continue + } + fmt.Println(v) + name := strings.Split(strings.Trim(strings.Trim(v, "\r"), "\t"), "\t")[0] + status := strings.Split(strings.Trim(strings.Trim(v, "\r"), "\t"), "\t")[1] + udid_map[name] = status + // devices = append(devices, getAndroidDeviceInfo(strings.Split(strings.Trim(strings.Trim(v, "\r"), "\t"), "\t")...)) + } + return udid_map +} + +type DeviceInfo struct { + Udid string `json:"string"` + Status string `json:"status"` +} + +func getAndroidDeviceInfo(args ...string) models.MonkeyDevice { + var di models.MonkeyDevice + di.Platform = "adr" + di.Udid = args[0] + if args[1] == "device" { + di.Status = "online" + } else { + di.Status = args[1] + } + + di.ProductName = getAndroidDeviceName(di.Udid) + return di +} + +func getAndroidDeviceName(udid string) string { + command := `getprop` // | grep product.marketname' + cmd := exec.Command("adb", "-s", udid, "shell", command) + out, err := cmd.CombinedOutput() + if err != nil { + fmt.Println(err) + return udid + } + strs := strings.Split(string(out), "\n") + device_name := "" + for _, v := range strs { + if strings.Contains(v, "product.brand") { + str := strings.Split(strings.Trim(v, "\r"), ": ")[1] + device_name = str[1 : len(str)-1] + break + } + } + fmt.Println(device_name) + return device_name +} + +func killPid(pid int) error { + cmd := exec.Command("kill", "-9", cast.ToString(pid)) + err := cmd.Run() + return err +} + +func checkTaskPids(pids []models.MonkeyPid) int { + if len(pids) == 0 { + return -1 + } + var strs []string + for _, v := range pids { + strs = append(strs, cast.ToString(v.PId)) + } + pids_str := strings.Join(strs, "|") + cmd_str := "ps -ef | grep -v -E 'bash|grep' | grep -E '" + pids_str + "'" + fmt.Println(cmd_str) + cmd := exec.Command("bash", "-c", cmd_str) + cmd.Run() + return cmd.ProcessState.ExitCode() +} diff --git a/monkey/device.go b/monkey/device.go new file mode 100644 index 0000000..f04154d --- /dev/null +++ b/monkey/device.go @@ -0,0 +1,31 @@ +package monkey + +import ( + "goqs/controllers" + "net/http" + + "github.com/gin-gonic/gin" +) + +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 获取设备列表 +// @Description 获取安卓设备列表 +// @accept x-www-form-urlencoded +// @Param platform query int false "平台:ios/adr" +// @Success 200 {object} models.Response "返回设备信息" +// @Router /api/monkey/v1/devices [get] +func GetDevices(c *gin.Context) { + rsp := controllers.NewResponse() + // var list []models.MonkeyDevice + + // db, err := dbsql.GetConn(dbsql.DSN) + // if err != nil { + // rsp.Error(err.Error()) + // c.JSON(http.StatusOK, rsp) + // return + // } + // defer dbsql.Close(db) + rsp.Success() + rsp.Data = GetAndroidDevices() + c.JSON(http.StatusOK, rsp) +} diff --git a/monkey/result.go b/monkey/result.go new file mode 100644 index 0000000..7bbabac --- /dev/null +++ b/monkey/result.go @@ -0,0 +1,96 @@ +package monkey + +import ( + "encoding/json" + "goqs/controllers" + "goqs/dbsql" + "goqs/models" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/spf13/cast" +) + +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 上报Monkey结果 +// @Description 上报Monkey结果 +// @accept x-www-form-urlencoded +// @Param task_id formData int true "任务id" +// @Param crash_log_list formData string false "要更新的任务状态" +// @Param activity_name_info formData string false "要更新的任务状态" +// @Param device_name formData string false "要更新的任务状态" +// @Param status formData string false "要更新的任务状态" +// @Success 200 {object} models.Response "返回更新后的任务信息" +// @Router /api/monkey/v1/task/result [post] +func UploadMonkeyResult(c *gin.Context) { + rsp := controllers.NewResponse() + + var res models.MonkeyResult + res.TaskId = cast.ToInt(c.PostForm("task_id")) + if res.TaskId < 1 { + rsp.Error("task_id error:" + c.PostForm("task_id")) + c.JSON(http.StatusOK, rsp) + } + res.CrashLogs = c.PostForm("crash_log_list") + res.ActivityNameInfo = c.PostForm("activity_name_info") + res.DeviceName = c.PostForm("device_name") + res.Logs = c.PostForm("log_list") + + db, err := dbsql.GetConn(dbsql.DSN) + if err != nil { + rsp.Error(err.Error()) + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + db.Create(&res) + if res.ID < 1 { + rsp.Error("保存Monkey任务失败") + c.JSON(http.StatusOK, rsp) + return + } + + rsp.Success() + rsp.Data = res + c.JSON(http.StatusOK, rsp) +} + +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 获取Monkey结果 +// @Description 通过任务id获取Monkey结果 +// @accept x-www-form-urlencoded +// @Param task_id query int true "任务id" +// @Success 200 {object} models.Response "返回任务结果" +// @Router /api/monkey/v1/task/result [get] +func GetMonkeyResult(c *gin.Context) { + rsp := controllers.NewResponse() + + var list []models.MonkeyResult + db, err := dbsql.GetConn(dbsql.DSN) + if err != nil { + rsp.Error(err.Error()) + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + db.Where("task_id = ?", c.Query("task_id")).Find(&list) + for i, _ := range list { + var strs []string + json.Unmarshal([]byte(list[i].CrashLogs), &strs) + if len(strs) > 0 { + list[i].CrashLogList = strs + } + json.Unmarshal([]byte(list[i].ActivityNameInfo), &strs) + if len(strs) > 0 { + list[i].ActivityList = strs + } + json.Unmarshal([]byte(list[i].Logs), &strs) + if len(strs) > 0 { + list[i].LogList = strs + } + } + + rsp.Success() + rsp.Data = list + c.JSON(http.StatusOK, rsp) +} diff --git a/monkey/task.go b/monkey/task.go index a3de70f..d3267bb 100644 --- a/monkey/task.go +++ b/monkey/task.go @@ -1,6 +1,7 @@ package monkey import ( + "fmt" "goqs/controllers" "goqs/dbsql" "goqs/models" @@ -34,6 +35,7 @@ func CreateTask(c *gin.Context) { rsp.Error(err.Error()) c.JSON(http.StatusOK, rsp) } + defer dbsql.Close(db) var task models.MonkeyTask task.Project = c.PostForm("project") @@ -49,13 +51,34 @@ func CreateTask(c *gin.Context) { // || task.Creator == "" if task.PackageName == "" || task.LaunchActivity == "" || task.DeviceAmount <= 0 || task.Platform == "" || - task.RunTime <= 10 || task.PackageURL == "" { + task.RunTime <= 10 { rsp.Error("get formdata error") rsp.Data = task c.JSON(http.StatusOK, rsp) return } + var devices []models.Device + is_online := false + db.Model(models.Device{}).Where("project = ?", task.Project).Find(&devices) + if len(devices) < 1 { + rsp.Error("该产品没有注册设备,请检查") + c.JSON(http.StatusOK, rsp) + return + } + m := GetAndroidDevices() + for _, v := range devices { + if _, ok := m[v.Udid]; ok { + is_online = true + break + } + } + if !is_online { + rsp.Error("该产品没有设备在线,请检查") + c.JSON(http.StatusOK, rsp) + return + } + db.Model(models.MonkeyTask{}).Create(&task) if db.Error != nil { rsp.Error(db.Error.Error()) @@ -73,7 +96,7 @@ func CreateTask(c *gin.Context) { // @Summary 更新Monkey任务状态 // @Description 更新Monkey任务状态,进行中为RUNNING,已完成为FINIASHED,如有错误为ERROR // @accept x-www-form-urlencoded -// @Param task_id formData int true "项目名" +// @Param task_id formData int true "任务id" // @Param status formData string false "要更新的任务状态" // @Success 200 {object} models.Response "返回更新后的任务信息" // @Router /api/monkey/v1/task/status [post] @@ -92,7 +115,10 @@ func UpdateTaskStatus(c *gin.Context) { if err != nil { rsp.Error(err.Error()) c.JSON(http.StatusOK, rsp) + return } + defer dbsql.Close(db) + var task models.MonkeyTask db.Where("id = ?", task_id).Find(&task) if task.Id <= 0 { @@ -108,6 +134,53 @@ func UpdateTaskStatus(c *gin.Context) { c.JSON(http.StatusOK, rsp) } +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 更新Monkey任务崩溃数量 +// @Description 更新Monkey任务崩溃数量 +// @accept x-www-form-urlencoded +// @Param task_id formData int true "任务id" +// @Param crash_count formData string false "要更新的崩溃数量" +// @Success 200 {object} models.Response "返回更新后的任务信息" +// @Router /api/monkey/v1/task/crash_count [post] +func UpdateTaskCrashCount(c *gin.Context) { + rsp := controllers.NewResponse() + + task_id := cast.ToInt(c.PostForm("task_id")) + // crash_count := cast.ToInt(c.DefaultPostForm("crash_count", "0")) + if task_id <= 0 { + rsp.Error("task_id error") + c.JSON(http.StatusOK, rsp) + return + } + // if crash_count <= 0 { + // rsp.Error("crash_count 错误或等于0,不更新") + // c.JSON(http.StatusOK, rsp) + // return + // } + + db, err := dbsql.GetConn(dbsql.DSN) + if err != nil { + rsp.Error(err.Error()) + c.JSON(http.StatusOK, rsp) + } + defer dbsql.Close(db) + var count int64 + db.Model(models.MonkeyResult{}).Where("task_id = ?", task_id).Count(&count) + + // var task models.MonkeyTask + // db.Where("id = ?", task_id).Find(&task) + // if task.Id <= 0 { + // rsp.Error("任务不存在") + // c.JSON(http.StatusOK, rsp) + // return + // } + db.Model(models.MonkeyTask{}).Where("id = ?", task_id).Update("crash_count", count) + + rsp.Success() + rsp.Data = count + c.JSON(http.StatusOK, rsp) +} + // @Tags Monkey相关 /api/monkey/v1/ // @Summary 获取任务列表 // @Description 获取任务列表 @@ -146,8 +219,32 @@ func GetTasks(c *gin.Context) { var count int64 db = db.Count(&count) db = dbsql.SetPageQuery(db, pageIndex, pageSize) - db.Order("id desc").Find(&list) + dbsql.Close(db) + + db, _ = dbsql.GetConn(dbsql.DSN) + for i, v := range list { + var count int64 + db.Model(models.MonkeyActivity{}).Where("task_id = ?", list[i].Id).Count(&count) + list[i].CoveredAcitvities = int(count) + // 如果状态在 进行中 or 取消中,则检查进程状态 + if v.Status == "RUNNING" || v.Status == "CANCELING" { + var pids []models.MonkeyPid + db.Model(models.MonkeyPid{}).Where("task_id = ?", v.Id).Find(&pids) + if code := checkTaskPids(pids); code == 0 { + list[i].Status = "RUNNING" + } else if code == 1 { + if v.Status == "CANCELING" { + list[i].Status = "CANCEL" + db.Model(models.MonkeyTask{}).Where("id = ?", v.Id).Update("status", list[i].Status) + } else if v.Status == "RUNNING" { + list[i].Status = "FINISH" + db.Model(models.MonkeyTask{}).Where("id = ?", v.Id).Update("status", list[i].Status) + } + } + } + } + dbsql.Close(db) p.MaxPage = count/(int64(p.Size)+1) + 1 p.List = list @@ -157,3 +254,138 @@ func GetTasks(c *gin.Context) { rsp.Data = p c.JSON(http.StatusOK, rsp) } + +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 获取monkey任务信息 +// @Description 根据id获取monkey任务信息 +// @accept x-www-form-urlencoded +// @Param id query int false "任务id" +// @Success 200 {object} models.Response "返回monkey任务信息" +// @Router /api/monkey/v1/task [get] +func GetTaskById(c *gin.Context) { + var rsp models.Response + + db, err := dbsql.GetConn(dbsql.DSN) + if rsp.CheckErr(err) { + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + + var data models.MonkeyTask + + db = db.Model(&models.MonkeyTask{}) + db.Model(models.MonkeyActivity{}).Where("id = ?", c.DefaultQuery("id", "0")).Last(&data) + dbsql.Close(db) + + db, _ = dbsql.GetConn(dbsql.DSN) + var count int64 + db.Where("task_id = ?", data.Id).Count(&count) + data.CoveredAcitvities = int(count) + dbsql.Close(db) + + if data.Id < 1 { + rsp.Error("查找不到monkey任务信息,id=" + c.Query("id")) + c.JSON(http.StatusOK, rsp) + return + } + + rsp.Success() + rsp.Data = data + c.JSON(http.StatusOK, rsp) +} + +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 上传Logcat日志 +// @Description 上传Logcat日志 +// @accept x-www-form-urlencoded +// @Success 200 {object} models.Response "返回成功或失败" +// @Router /webdav/monkey/task/:id/:filename [put] +func TaskReport(c *gin.Context) { + + fmt.Println(c.Request.Header) + data, err := c.GetRawData() + if err != nil { + fmt.Println(err) + c.String(http.StatusOK, "OK") + return + } + fmt.Println(len(data)) + CreateDir("./files") + CreateDir("./files/monkey") + CreateDir("./files/monkey/log") + CreateDir("./files/monkey/log/" + c.Param("id")) + CreateAndWriteFile("./files//monkey/log/"+c.Param("id")+"/"+c.Param("filename"), data) + c.String(http.StatusOK, "OK") +} + +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 上报进程id +// @Description 上传进程id并关联到任务 +// @accept x-www-form-urlencoded +// @Param task_id formData int true "任务id" +// @Param pid formData int true "进程id" +// @Success 200 {object} models.Response "返回成功或失败" +// @Router /api/monkey/v1/task/pid [post] +func UpdatePids(c *gin.Context) { + var rsp models.Response + + db, err := dbsql.GetConn(dbsql.DSN) + if rsp.CheckErr(err) { + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + var obj models.MonkeyPid + if task_id := cast.ToInt(c.PostForm("task_id")); task_id > 0 { + obj.TaskId = task_id + } else { + rsp.Error("task_id获取失败") + c.JSON(http.StatusOK, rsp) + return + } + if pid := cast.ToInt(c.PostForm("pid")); pid > 0 { + obj.PId = pid + } else { + rsp.Error("pid获取失败") + c.JSON(http.StatusOK, rsp) + return + } + db.Create(&obj) + + rsp.Success() + rsp.Data = obj + c.JSON(http.StatusOK, rsp) +} + +// @Tags Monkey相关 /api/monkey/v1/ +// @Summary 停止monkey任务 +// @Description 停止monkey任务,杀死所有关联任务的进程id +// @accept x-www-form-urlencoded +// @Param task_id formData int true "任务id" +// @Success 200 {object} models.Response "返回成功或失败" +// @Router /api/monkey/v1/task/stop [post] +func StopMonkeyTask(c *gin.Context) { + var rsp models.Response + var pids []int + + if task_id := cast.ToInt(c.PostForm("task_id")); task_id > 0 { + db, err := dbsql.GetConn(dbsql.DSN) + if rsp.CheckErr(err) { + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + db.Model(models.MonkeyTask{}).Where("id = ?", task_id).Update("status", "CANCELING") + var list []models.MonkeyPid + db.Where("task_id = ? and is_del = 0", task_id).Find(&list) + for _, v := range list { + killPid(v.PId) + pids = append(pids, v.PId) + } + } + + rsp.Success() + rsp.Data = pids + c.JSON(http.StatusOK, rsp) +} diff --git a/test/test.go b/test/test.go new file mode 100644 index 0000000..707d490 --- /dev/null +++ b/test/test.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "goqs/monkey" +) + +func main() { + err := monkey.CreateDir("files") + if err != nil { + fmt.Println(err) + } + err = monkey.CreateDir("files/1") + if err != nil { + fmt.Println(err) + } + err = monkey.CreateAndWriteFile("files/1/2.txt", []byte("hidiuniduini")) + if err != nil { + fmt.Println(err) + } +}