From d9964d52ba4ab1d01805631d2b096e07126cfa2f Mon Sep 17 00:00:00 2001 From: zhangshuai Date: Thu, 10 Oct 2024 17:15:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20job=20=E6=8E=A5=E5=8F=A3=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../net/geedge/asw/common/util/RCode.java | 1 + .../runner/controller/JobController.java | 40 +- .../runner/controller/RunnerController.java | 348 +++++++++--------- .../geedge/asw/module/runner/dao/JobDao.java | 2 - .../asw/module/runner/entity/JobEntity.java | 17 +- .../asw/module/runner/entity/PcapEntity.java | 3 +- .../module/runner/service/IJobService.java | 11 +- .../module/runner/service/IPcapService.java | 3 - .../module/runner/service/IRunnerService.java | 34 +- .../runner/service/impl/JobServiceImpl.java | 140 +++---- .../runner/service/impl/PcapServiceImpl.java | 19 +- .../service/impl/RunnerServiceImpl.java | 102 ++--- .../resources/db/mapper/runner/JobMapper.xml | 72 +--- .../resources/db/migration/R__AZ_sys_i18n.sql | 5 +- .../db/migration/V1.0.01__INIT_TABLES.sql | 8 +- 15 files changed, 363 insertions(+), 442 deletions(-) diff --git a/src/main/java/net/geedge/asw/common/util/RCode.java b/src/main/java/net/geedge/asw/common/util/RCode.java index e448607..a93bcac 100644 --- a/src/main/java/net/geedge/asw/common/util/RCode.java +++ b/src/main/java/net/geedge/asw/common/util/RCode.java @@ -87,6 +87,7 @@ public enum RCode { ENVIRONMENT_NOT_EXIST(601002, "environment does not exist"), ENVIRONMENT_USED(601003, "The environment is already in use"), ENVIRONMENT_STATUS_ERROR(601004, "The environment status is unavailable"), + ENVIRONMENT_ID_CANNOT_EMPTY(601005, "environment id cannot be empty"), diff --git a/src/main/java/net/geedge/asw/module/runner/controller/JobController.java b/src/main/java/net/geedge/asw/module/runner/controller/JobController.java index b12aa05..8e1771e 100644 --- a/src/main/java/net/geedge/asw/module/runner/controller/JobController.java +++ b/src/main/java/net/geedge/asw/module/runner/controller/JobController.java @@ -10,55 +10,67 @@ import net.geedge.asw.module.runner.service.IJobService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.Arrays; +import java.util.List; import java.util.Map; @RestController -@RequestMapping("/api/v1/job") +@RequestMapping("/api/v1/workspace") public class JobController { @Autowired private IJobService jobService; - @GetMapping("/{id}") - public R detail(@PathVariable("id") String id) { + @GetMapping("/{workspaceId}/job/{id}") + public R detail(@PathVariable("workspaceId") String workspaceId, + @PathVariable("id") String id) { JobEntity jobEntity = jobService.queryInfo(id); return R.ok().putData("record", jobEntity); } - @GetMapping - public R list(@RequestParam Map params) { + @GetMapping("/{workspaceId}/job") + public R list(@PathVariable("workspaceId") String workspaceId, + @RequestParam Map params) { T.VerifyUtil.is(params).notNull() .and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); Page page = jobService.queryList(params); return R.ok(page); } - @PostMapping - public R add(@RequestBody JobEntity entity) { + @PostMapping("/{workspaceId}/job") + public R add(@PathVariable("workspaceId") String workspaceId, + @RequestBody JobEntity entity) { T.VerifyUtil.is(entity).notNull() - .and(entity.getRunnerId()).notEmpty(RCode.RUNNER_ID_CANNOT_EMPTY) + .and(entity.getEnvironmentId()).notEmpty(RCode.ENVIRONMENT_ID_CANNOT_EMPTY) .and(entity.getPackageId()).notEmpty(RCode.PACKAGE_ID_CANNOT_EMPTY) + .and(entity.getPlaybookId()).notEmpty(RCode.PLAYBOOK_ID_CANNOT_EMPTY) .and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); + entity.setEnvId(entity.getEnvironmentId()); + JobEntity jobEntity = jobService.saveJob(entity); return R.ok().putData("id", jobEntity.getId()); } - @DeleteMapping - public R delete(String[] ids) { + @DeleteMapping("/{workspaceId}/job") + public R delete(@PathVariable("workspaceId") String workspaceId, + @RequestParam String ids) { T.VerifyUtil.is(ids).notEmpty(); - jobService.removeJob(T.ListUtil.of(ids)); + List idList = Arrays.asList(ids.split(",")); + jobService.removeJob(idList); return R.ok(); } - @PutMapping("/cancel") - public R cancel(String[] ids) { + @PutMapping("/{workspaceId}/job/cancel") + public R cancel(@PathVariable("workspaceId") String workspaceId, + @RequestParam String ids) { T.VerifyUtil.is(ids).notEmpty(); + List idList = Arrays.asList(ids.split(",")); // TODO 其他处理 // update state jobService.update(new LambdaUpdateWrapper() - .in(JobEntity::getId, ids) + .in(JobEntity::getId, idList) .set(JobEntity::getStatus, "cancel") ); return R.ok(); diff --git a/src/main/java/net/geedge/asw/module/runner/controller/RunnerController.java b/src/main/java/net/geedge/asw/module/runner/controller/RunnerController.java index e7499c8..2897ef7 100644 --- a/src/main/java/net/geedge/asw/module/runner/controller/RunnerController.java +++ b/src/main/java/net/geedge/asw/module/runner/controller/RunnerController.java @@ -1,174 +1,174 @@ -package net.geedge.asw.module.runner.controller; - -import cn.dev33.satoken.annotation.SaIgnore; -import cn.hutool.core.lang.Opt; -import cn.hutool.log.Log; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import jakarta.servlet.http.HttpServletResponse; -import net.geedge.asw.common.util.R; -import net.geedge.asw.common.util.RCode; -import net.geedge.asw.common.util.T; -import net.geedge.asw.module.app.entity.PackageEntity; -import net.geedge.asw.module.runner.entity.JobEntity; -import net.geedge.asw.module.runner.entity.PlaybookEntity; -import net.geedge.asw.module.runner.entity.RunnerEntity; -import net.geedge.asw.module.runner.service.IJobService; -import net.geedge.asw.module.runner.service.IRunnerService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.util.Map; - -@RestController -@RequestMapping("/api/v1/runner") -public class RunnerController { - - private static final Log log = Log.get(); - - @Autowired - private IJobService jobService; - - @Autowired - private IRunnerService runnerService; - - @GetMapping("/{id}") - public R detail(@PathVariable("id") String id) { - RunnerEntity runnerEntity = runnerService.getById(id); - return R.ok().putData("record", runnerEntity); - } - - @GetMapping - public R list(@RequestParam Map params) { - T.VerifyUtil.is(params).notNull() - .and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); - - Page page = runnerService.queryList(params); - return R.ok(page); - } - - @PostMapping - public R add(@RequestBody RunnerEntity entity) { - T.VerifyUtil.is(entity).notNull() - .and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); - - RunnerEntity runner = runnerService.saveRunner(entity); - return R.ok().putData("record", runner); - } - - @PutMapping - public R update(@RequestBody RunnerEntity entity) { - T.VerifyUtil.is(entity).notNull() - .and(entity.getId()).notEmpty(RCode.ID_CANNOT_EMPTY) - .and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); - - RunnerEntity runner = runnerService.updateRunner(entity); - return R.ok().putData("record", runner); - } - - @DeleteMapping("/{id}") - public R delete(@PathVariable("id") String id) { - runnerService.removeById(id); - return R.ok(); - } - - @SaIgnore - @PostMapping("/register") - public void register(@RequestHeader("Authorization") String token, HttpServletResponse response) throws IOException { - RunnerEntity runner = runnerService.getOne(new LambdaUpdateWrapper().eq(RunnerEntity::getToken, token)); - String status = Opt.ofNullable(runner).map(RunnerEntity::getStatus).orElseGet(() -> null); - if (!T.StrUtil.equals("online", status)) { - log.warn("[register] [runner is offline] [token: {}]", token); - response.sendError(HttpServletResponse.SC_FORBIDDEN, "Runner is offline"); - } - } - - @SaIgnore - @PostMapping("/heartbeat") - public void heartbeat(@RequestHeader("Authorization") String token, @RequestBody Map platformMap, - HttpServletResponse response) throws IOException { - RunnerEntity runner = runnerService.getOne(new LambdaUpdateWrapper().eq(RunnerEntity::getToken, token)); - String status = Opt.ofNullable(runner).map(RunnerEntity::getStatus).orElseGet(() -> null); - if (!T.StrUtil.equals("online", status)) { - log.warn("[heartbeat] [runner is offline] [token: {}]", token); - response.sendError(HttpServletResponse.SC_FORBIDDEN, "Runner is offline"); - return; - } - - // update last_heartbeat_timestamp - runnerService.update(new LambdaUpdateWrapper() - .set(RunnerEntity::getLastHeartbeatTimestamp, System.currentTimeMillis()) - .eq(RunnerEntity::getId, runner.getId())); - - // findjob by platform - String platform = platformMap.entrySet().stream().filter(entry -> entry.getValue() > 0).findFirst().map(entry -> entry.getKey()).orElseGet(null); - JobEntity job = jobService.assignPendingJob(runner.getId(), platform); - if (T.ObjectUtil.isNotNull(job)) { - // package - PackageEntity pkg = job.getPkg(); - Map pkgInfo = T.MapUtil.builder("id", pkg.getId()) - .put("platform", pkg.getPlatform()) - .put("identifier", pkg.getIdentifier()) - .put("version", pkg.getVersion()) - .build(); - - // playbook - PlaybookEntity playbook = job.getPlaybook(); - Map pbInfo = T.MapUtil.builder("id", playbook.getId()) - .put("name", playbook.getName()) - .build(); - - // response job info - Map responseData = T.MapUtil.builder() - .put("id", job.getId()) - .put("pkg", pkgInfo) - .put("playbook", pbInfo) - .build(); - response.setCharacterEncoding("UTF-8"); - response.setContentType("text/html; charset=UTF-8"); - response.getWriter().write(T.JSONUtil.toJsonStr(responseData)); - } - } - - @SaIgnore - @PutMapping("/trace/{jobId}") - public void trace(@RequestHeader("Authorization") String token, @PathVariable String jobId, @RequestBody byte[] bytes, - HttpServletResponse response) throws IOException { - RunnerEntity runner = runnerService.getOne(new LambdaUpdateWrapper().eq(RunnerEntity::getToken, token)); - String status = Opt.ofNullable(runner).map(RunnerEntity::getStatus).orElseGet(() -> null); - if (!T.StrUtil.equals("online", status)) { - log.warn("[trace] [runner is offline] [token: {}]", token); - response.sendError(HttpServletResponse.SC_FORBIDDEN, "Runner is offline"); - return; - } - - try { - // 追加到文件中 - String content = T.StrUtil.str(bytes, T.CharsetUtil.CHARSET_UTF_8); - jobService.appendTraceLogStrToFile(jobId, content); - } catch (Exception e) { - log.error("[trace] [error] [job: {}]", jobId); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - - @SaIgnore - @PutMapping("/jobResult/{jobId}") - public void jobResult(@RequestHeader("Authorization") String token, @PathVariable String jobId, @RequestParam String state, - @RequestParam(value = "file", required = false) MultipartFile pcapFile, - HttpServletResponse response) throws IOException { - RunnerEntity runner = runnerService.getOne(new LambdaUpdateWrapper().eq(RunnerEntity::getToken, token)); - String status = Opt.ofNullable(runner).map(RunnerEntity::getStatus).orElseGet(() -> null); - if (!T.StrUtil.equals("online", status)) { - log.warn("[trace] [runner is offline] [token: {}]", token); - response.sendError(HttpServletResponse.SC_FORBIDDEN, "Runner is offline"); - return; - } - - // 更新任务状态 - jobService.updateJobResult(jobId, state, pcapFile); - } - -} \ No newline at end of file +//package net.geedge.asw.module.runner.controller; +// +//import cn.dev33.satoken.annotation.SaIgnore; +//import cn.hutool.core.lang.Opt; +//import cn.hutool.log.Log; +//import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +//import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +//import jakarta.servlet.http.HttpServletResponse; +//import net.geedge.asw.common.util.R; +//import net.geedge.asw.common.util.RCode; +//import net.geedge.asw.common.util.T; +//import net.geedge.asw.module.app.entity.PackageEntity; +//import net.geedge.asw.module.runner.entity.JobEntity; +//import net.geedge.asw.module.runner.entity.PlaybookEntity; +//import net.geedge.asw.module.runner.entity.RunnerEntity; +//import net.geedge.asw.module.runner.service.IJobService; +//import net.geedge.asw.module.runner.service.IRunnerService; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.web.bind.annotation.*; +//import org.springframework.web.multipart.MultipartFile; +// +//import java.io.IOException; +//import java.util.Map; +// +//@RestController +//@RequestMapping("/api/v1/runner") +//public class RunnerController { +// +// private static final Log log = Log.get(); +// +// @Autowired +// private IJobService jobService; +// +// @Autowired +// private IRunnerService runnerService; +// +// @GetMapping("/{id}") +// public R detail(@PathVariable("id") String id) { +// RunnerEntity runnerEntity = runnerService.getById(id); +// return R.ok().putData("record", runnerEntity); +// } +// +// @GetMapping +// public R list(@RequestParam Map params) { +// T.VerifyUtil.is(params).notNull() +// .and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); +// +// Page page = runnerService.queryList(params); +// return R.ok(page); +// } +// +// @PostMapping +// public R add(@RequestBody RunnerEntity entity) { +// T.VerifyUtil.is(entity).notNull() +// .and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); +// +// RunnerEntity runner = runnerService.saveRunner(entity); +// return R.ok().putData("record", runner); +// } +// +// @PutMapping +// public R update(@RequestBody RunnerEntity entity) { +// T.VerifyUtil.is(entity).notNull() +// .and(entity.getId()).notEmpty(RCode.ID_CANNOT_EMPTY) +// .and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); +// +// RunnerEntity runner = runnerService.updateRunner(entity); +// return R.ok().putData("record", runner); +// } +// +// @DeleteMapping("/{id}") +// public R delete(@PathVariable("id") String id) { +// runnerService.removeById(id); +// return R.ok(); +// } +// +// @SaIgnore +// @PostMapping("/register") +// public void register(@RequestHeader("Authorization") String token, HttpServletResponse response) throws IOException { +// RunnerEntity runner = runnerService.getOne(new LambdaUpdateWrapper().eq(RunnerEntity::getToken, token)); +// String status = Opt.ofNullable(runner).map(RunnerEntity::getStatus).orElseGet(() -> null); +// if (!T.StrUtil.equals("online", status)) { +// log.warn("[register] [runner is offline] [token: {}]", token); +// response.sendError(HttpServletResponse.SC_FORBIDDEN, "Runner is offline"); +// } +// } +// +// @SaIgnore +// @PostMapping("/heartbeat") +// public void heartbeat(@RequestHeader("Authorization") String token, @RequestBody Map platformMap, +// HttpServletResponse response) throws IOException { +// RunnerEntity runner = runnerService.getOne(new LambdaUpdateWrapper().eq(RunnerEntity::getToken, token)); +// String status = Opt.ofNullable(runner).map(RunnerEntity::getStatus).orElseGet(() -> null); +// if (!T.StrUtil.equals("online", status)) { +// log.warn("[heartbeat] [runner is offline] [token: {}]", token); +// response.sendError(HttpServletResponse.SC_FORBIDDEN, "Runner is offline"); +// return; +// } +// +// // update last_heartbeat_timestamp +// runnerService.update(new LambdaUpdateWrapper() +// .set(RunnerEntity::getLastHeartbeatTimestamp, System.currentTimeMillis()) +// .eq(RunnerEntity::getId, runner.getId())); +// +// // findjob by platform +// String platform = platformMap.entrySet().stream().filter(entry -> entry.getValue() > 0).findFirst().map(entry -> entry.getKey()).orElseGet(null); +// JobEntity job = jobService.assignPendingJob(runner.getId(), platform); +// if (T.ObjectUtil.isNotNull(job)) { +// // package +// PackageEntity pkg = job.getPkg(); +// Map pkgInfo = T.MapUtil.builder("id", pkg.getId()) +// .put("platform", pkg.getPlatform()) +// .put("identifier", pkg.getIdentifier()) +// .put("version", pkg.getVersion()) +// .build(); +// +// // playbook +// PlaybookEntity playbook = job.getPlaybook(); +// Map pbInfo = T.MapUtil.builder("id", playbook.getId()) +// .put("name", playbook.getName()) +// .build(); +// +// // response job info +// Map responseData = T.MapUtil.builder() +// .put("id", job.getId()) +// .put("pkg", pkgInfo) +// .put("playbook", pbInfo) +// .build(); +// response.setCharacterEncoding("UTF-8"); +// response.setContentType("text/html; charset=UTF-8"); +// response.getWriter().write(T.JSONUtil.toJsonStr(responseData)); +// } +// } +// +// @SaIgnore +// @PutMapping("/trace/{jobId}") +// public void trace(@RequestHeader("Authorization") String token, @PathVariable String jobId, @RequestBody byte[] bytes, +// HttpServletResponse response) throws IOException { +// RunnerEntity runner = runnerService.getOne(new LambdaUpdateWrapper().eq(RunnerEntity::getToken, token)); +// String status = Opt.ofNullable(runner).map(RunnerEntity::getStatus).orElseGet(() -> null); +// if (!T.StrUtil.equals("online", status)) { +// log.warn("[trace] [runner is offline] [token: {}]", token); +// response.sendError(HttpServletResponse.SC_FORBIDDEN, "Runner is offline"); +// return; +// } +// +// try { +// // 追加到文件中 +// String content = T.StrUtil.str(bytes, T.CharsetUtil.CHARSET_UTF_8); +// jobService.appendTraceLogStrToFile(jobId, content); +// } catch (Exception e) { +// log.error("[trace] [error] [job: {}]", jobId); +// response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); +// } +// } +// +// @SaIgnore +// @PutMapping("/jobResult/{jobId}") +// public void jobResult(@RequestHeader("Authorization") String token, @PathVariable String jobId, @RequestParam String state, +// @RequestParam(value = "file", required = false) MultipartFile pcapFile, +// HttpServletResponse response) throws IOException { +// RunnerEntity runner = runnerService.getOne(new LambdaUpdateWrapper().eq(RunnerEntity::getToken, token)); +// String status = Opt.ofNullable(runner).map(RunnerEntity::getStatus).orElseGet(() -> null); +// if (!T.StrUtil.equals("online", status)) { +// log.warn("[trace] [runner is offline] [token: {}]", token); +// response.sendError(HttpServletResponse.SC_FORBIDDEN, "Runner is offline"); +// return; +// } +// +// // 更新任务状态 +// jobService.updateJobResult(jobId, state, pcapFile); +// } +// +//} \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/runner/dao/JobDao.java b/src/main/java/net/geedge/asw/module/runner/dao/JobDao.java index c65b7d9..57a7240 100644 --- a/src/main/java/net/geedge/asw/module/runner/dao/JobDao.java +++ b/src/main/java/net/geedge/asw/module/runner/dao/JobDao.java @@ -14,6 +14,4 @@ public interface JobDao extends BaseMapper{ List queryList(IPage page, Map params); - JobEntity getPendingJobByPlatform(@Param("platform") String platform); - } diff --git a/src/main/java/net/geedge/asw/module/runner/entity/JobEntity.java b/src/main/java/net/geedge/asw/module/runner/entity/JobEntity.java index 151c376..11c529d 100644 --- a/src/main/java/net/geedge/asw/module/runner/entity/JobEntity.java +++ b/src/main/java/net/geedge/asw/module/runner/entity/JobEntity.java @@ -6,8 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; -import net.geedge.asw.module.app.entity.ApplicationEntity; import net.geedge.asw.module.app.entity.PackageEntity; +import net.geedge.asw.module.environment.entity.EnvironmentEntity; @Data @TableName("job") @@ -15,12 +15,10 @@ public class JobEntity { @TableId(type = IdType.ASSIGN_UUID) private String id; - private String playbookId; private String packageId; - private String runnerId; - private String scheduleId; - private String signatureIds; - private String tags; + private String envId; + private String playbookId; + private String playbookParam; private Long startTimestamp; private Long endTimestamp; private String status; @@ -35,17 +33,14 @@ public class JobEntity { private String workspaceId; @TableField(exist = false) - private String workbookId; - - @TableField(exist = false) - private ApplicationEntity application; + private String environmentId; @TableField(exist = false) @JsonProperty(value = "package") private PackageEntity pkg; @TableField(exist = false) - private RunnerEntity runner; + private EnvironmentEntity environment; @TableField(exist = false) private PlaybookEntity playbook; diff --git a/src/main/java/net/geedge/asw/module/runner/entity/PcapEntity.java b/src/main/java/net/geedge/asw/module/runner/entity/PcapEntity.java index 4d5cf27..94c3c42 100644 --- a/src/main/java/net/geedge/asw/module/runner/entity/PcapEntity.java +++ b/src/main/java/net/geedge/asw/module/runner/entity/PcapEntity.java @@ -10,6 +10,7 @@ import lombok.Data; import net.geedge.asw.common.util.T; import net.geedge.asw.module.app.entity.ApplicationEntity; import net.geedge.asw.module.app.entity.PackageEntity; +import net.geedge.asw.module.environment.entity.EnvironmentEntity; import net.geedge.asw.module.workspace.entity.WorkspaceEntity; import java.nio.file.Path; @@ -45,7 +46,7 @@ public class PcapEntity { private PackageEntity pkg; @TableField(exist = false) - private RunnerEntity runner; + private EnvironmentEntity environment; @TableField(exist = false) private PlaybookEntity playbook; diff --git a/src/main/java/net/geedge/asw/module/runner/service/IJobService.java b/src/main/java/net/geedge/asw/module/runner/service/IJobService.java index c0341e8..ec148d9 100644 --- a/src/main/java/net/geedge/asw/module/runner/service/IJobService.java +++ b/src/main/java/net/geedge/asw/module/runner/service/IJobService.java @@ -3,7 +3,6 @@ package net.geedge.asw.module.runner.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import net.geedge.asw.module.runner.entity.JobEntity; -import org.springframework.web.multipart.MultipartFile; import java.util.List; import java.util.Map; @@ -18,10 +17,10 @@ public interface IJobService extends IService{ void removeJob(List ids); - JobEntity assignPendingJob(String id, String platform); - - void appendTraceLogStrToFile(String jobId, String content) throws RuntimeException; - - void updateJobResult(String jobId, String state, MultipartFile pcapFile); +// JobEntity assignPendingJob(String id, String platform); +// +// void appendTraceLogStrToFile(String jobId, String content) throws RuntimeException; +// +// void updateJobResult(String jobId, String state, MultipartFile pcapFile); } diff --git a/src/main/java/net/geedge/asw/module/runner/service/IPcapService.java b/src/main/java/net/geedge/asw/module/runner/service/IPcapService.java index 07c8870..c76de40 100644 --- a/src/main/java/net/geedge/asw/module/runner/service/IPcapService.java +++ b/src/main/java/net/geedge/asw/module/runner/service/IPcapService.java @@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import net.geedge.asw.module.runner.entity.PcapEntity; import org.springframework.core.io.Resource; -import org.springframework.web.bind.annotation.RequestParam; import java.util.Map; @@ -14,8 +13,6 @@ public interface IPcapService extends IService{ Page queryList(Map params); - PcapEntity savePcap(String jobId, Resource fileResource); - PcapEntity savePcap(Resource fileResource,String... params); void deletePcap(String... ids); diff --git a/src/main/java/net/geedge/asw/module/runner/service/IRunnerService.java b/src/main/java/net/geedge/asw/module/runner/service/IRunnerService.java index 8a59016..e2a6af8 100644 --- a/src/main/java/net/geedge/asw/module/runner/service/IRunnerService.java +++ b/src/main/java/net/geedge/asw/module/runner/service/IRunnerService.java @@ -1,17 +1,17 @@ -package net.geedge.asw.module.runner.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import net.geedge.asw.module.runner.entity.RunnerEntity; - -import java.util.Map; - -public interface IRunnerService extends IService{ - - Page queryList(Map params); - - RunnerEntity saveRunner(RunnerEntity entity); - - RunnerEntity updateRunner(RunnerEntity entity); - -} +//package net.geedge.asw.module.runner.service; +// +//import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +//import com.baomidou.mybatisplus.extension.service.IService; +//import net.geedge.asw.module.runner.entity.RunnerEntity; +// +//import java.util.Map; +// +//public interface IRunnerService extends IService{ +// +// Page queryList(Map params); +// +// RunnerEntity saveRunner(RunnerEntity entity); +// +// RunnerEntity updateRunner(RunnerEntity entity); +// +//} diff --git a/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java b/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java index d27a384..c530fd5 100644 --- a/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/runner/service/impl/JobServiceImpl.java @@ -1,33 +1,25 @@ package net.geedge.asw.module.runner.service.impl; import cn.dev33.satoken.stp.StpUtil; -import cn.hutool.core.io.IORuntimeException; import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import net.geedge.asw.common.util.RCode; import net.geedge.asw.common.util.T; -import net.geedge.asw.module.app.entity.ApplicationEntity; import net.geedge.asw.module.app.entity.PackageEntity; -import net.geedge.asw.module.app.service.IApplicationService; import net.geedge.asw.module.app.service.IPackageService; +import net.geedge.asw.module.environment.entity.EnvironmentEntity; +import net.geedge.asw.module.environment.service.IEnvironmentService; import net.geedge.asw.module.runner.dao.JobDao; import net.geedge.asw.module.runner.entity.JobEntity; -import net.geedge.asw.module.runner.entity.PcapEntity; import net.geedge.asw.module.runner.entity.PlaybookEntity; -import net.geedge.asw.module.runner.entity.RunnerEntity; import net.geedge.asw.module.runner.service.IJobService; -import net.geedge.asw.module.runner.service.IPcapService; import net.geedge.asw.module.runner.service.IPlaybookService; -import net.geedge.asw.module.runner.service.IRunnerService; import net.geedge.asw.module.runner.util.RunnerConstant; -import net.geedge.asw.module.workbook.service.IWorkbookResourceService; -import net.geedge.asw.module.workbook.util.WorkbookConstant; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.util.List; @@ -39,10 +31,7 @@ public class JobServiceImpl extends ServiceImpl implements IJ private static final Log log = Log.get(); @Autowired - private IPcapService pcapService; - - @Autowired - private IRunnerService runnerService; + private IEnvironmentService environmentService; @Autowired private IPlaybookService playbookService; @@ -50,11 +39,6 @@ public class JobServiceImpl extends ServiceImpl implements IJ @Autowired private IPackageService packageService; - @Autowired - private IApplicationService applicationService; - - @Autowired - private IWorkbookResourceService workbookResourceService; /** * rootPath/result/{jobId} @@ -71,8 +55,8 @@ public class JobServiceImpl extends ServiceImpl implements IJ JobEntity job = this.getById(id); T.VerifyUtil.is(job).notNull(RCode.SYS_RECORD_NOT_FOUND); - RunnerEntity runner = runnerService.getById(job.getRunnerId()); - job.setRunner(runner); + EnvironmentEntity env = environmentService.getById(job.getEnvId()); + job.setEnvironment(env); PlaybookEntity playbook = playbookService.getById(job.getPlaybookId()); job.setPlaybook(playbook); @@ -97,13 +81,11 @@ public class JobServiceImpl extends ServiceImpl implements IJ entity.setUpdateTimestamp(System.currentTimeMillis()); entity.setCreateUserId(StpUtil.getLoginIdAsString()); entity.setUpdateUserId(StpUtil.getLoginIdAsString()); + entity.setStatus(RunnerConstant.JobStatus.CREATED.getValue()); // save this.save(entity); - // workbook resource - workbookResourceService.saveResource(entity.getWorkbookId(), entity.getId(), WorkbookConstant.ResourceType.JOB.getValue()); - // trace log file path File traceLogFile = T.FileUtil.file(this.getJobResultPath(entity.getId()), "trace.log"); this.update(new LambdaUpdateWrapper() @@ -117,63 +99,61 @@ public class JobServiceImpl extends ServiceImpl implements IJ public void removeJob(List ids) { // remove this.removeBatchByIds(ids); - // workbook resource - workbookResourceService.removeResource(ids, WorkbookConstant.ResourceType.JOB.getValue()); } - @Override - public synchronized JobEntity assignPendingJob(String runnerId, String platform) { - if (T.StrUtil.hasEmpty(runnerId, platform)) { - return null; - } - // query - JobEntity job = this.getBaseMapper().getPendingJobByPlatform(platform); - if (T.ObjectUtil.isNotNull(job)) { - // update - this.update(new LambdaUpdateWrapper() - .set(JobEntity::getRunnerId, runnerId) - .set(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue()) - .set(JobEntity::getStartTimestamp, System.currentTimeMillis()) - .eq(JobEntity::getId, job.getId()) - ); - } - return job; - } - - @Override - public void appendTraceLogStrToFile(String jobId, String content) throws RuntimeException { - try { - JobEntity job = this.getById(jobId); - if (T.StrUtil.isEmpty(job.getLogPath())) { - File traceLogFile = T.FileUtil.file(this.getJobResultPath(jobId), "trace.log"); - job.setLogPath(traceLogFile.getPath()); - } - // append content - T.FileUtil.appendString(content, T.FileUtil.file(job.getLogPath()), T.CharsetUtil.CHARSET_UTF_8); - } catch (IORuntimeException e) { - log.error(e, "[appendTraceLogStrToFile] [error] [job: {}] [content: {}]", jobId, content); - throw new RuntimeException(e.getMessage()); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateJobResult(String jobId, String state, MultipartFile pcapFile) { - String pcapId = T.StrUtil.EMPTY; - // save pcap file - if (T.ObjectUtil.isNotNull(pcapFile)) { - PcapEntity pcapEntity = pcapService.savePcap(jobId, pcapFile.getResource()); - pcapId = pcapEntity.getId(); - } - - // update job status&pcap_id - state = T.StrUtil.equals("success", state) ? RunnerConstant.JobStatus.PASSED.getValue() : state; - this.update(new LambdaUpdateWrapper() - .set(JobEntity::getStatus, state) - .set(T.StrUtil.isNotEmpty(pcapId), JobEntity::getPcapId, pcapId) - .set(JobEntity::getEndTimestamp, System.currentTimeMillis()) - .eq(JobEntity::getId, jobId) - ); - } +// @Override +// public synchronized JobEntity assignPendingJob(String runnerId, String platform) { +// if (T.StrUtil.hasEmpty(runnerId, platform)) { +// return null; +// } +// // query +// JobEntity job = this.getBaseMapper().getPendingJobByPlatform(platform); +// if (T.ObjectUtil.isNotNull(job)) { +// // update +// this.update(new LambdaUpdateWrapper() +// .set(JobEntity::getRunnerId, runnerId) +// .set(JobEntity::getStatus, RunnerConstant.JobStatus.RUNNING.getValue()) +// .set(JobEntity::getStartTimestamp, System.currentTimeMillis()) +// .eq(JobEntity::getId, job.getId()) +// ); +// } +// return job; +// } +// +// @Override +// public void appendTraceLogStrToFile(String jobId, String content) throws RuntimeException { +// try { +// JobEntity job = this.getById(jobId); +// if (T.StrUtil.isEmpty(job.getLogPath())) { +// File traceLogFile = T.FileUtil.file(this.getJobResultPath(jobId), "trace.log"); +// job.setLogPath(traceLogFile.getPath()); +// } +// // append content +// T.FileUtil.appendString(content, T.FileUtil.file(job.getLogPath()), T.CharsetUtil.CHARSET_UTF_8); +// } catch (IORuntimeException e) { +// log.error(e, "[appendTraceLogStrToFile] [error] [job: {}] [content: {}]", jobId, content); +// throw new RuntimeException(e.getMessage()); +// } +// } +// +// @Override +// @Transactional(rollbackFor = Exception.class) +// public void updateJobResult(String jobId, String state, MultipartFile pcapFile) { +// String pcapId = T.StrUtil.EMPTY; +// // save pcap file +// if (T.ObjectUtil.isNotNull(pcapFile)) { +// PcapEntity pcapEntity = pcapService.savePcap(jobId, pcapFile.getResource()); +// pcapId = pcapEntity.getId(); +// } +// +// // update job status&pcap_id +// state = T.StrUtil.equals("success", state) ? RunnerConstant.JobStatus.PASSED.getValue() : state; +// this.update(new LambdaUpdateWrapper() +// .set(JobEntity::getStatus, state) +// .set(T.StrUtil.isNotEmpty(pcapId), JobEntity::getPcapId, pcapId) +// .set(JobEntity::getEndTimestamp, System.currentTimeMillis()) +// .eq(JobEntity::getId, jobId) +// ); +// } } diff --git a/src/main/java/net/geedge/asw/module/runner/service/impl/PcapServiceImpl.java b/src/main/java/net/geedge/asw/module/runner/service/impl/PcapServiceImpl.java index 5ff66f6..9d1322f 100644 --- a/src/main/java/net/geedge/asw/module/runner/service/impl/PcapServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/runner/service/impl/PcapServiceImpl.java @@ -9,27 +9,25 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import net.geedge.asw.common.config.SpringContextUtils; import net.geedge.asw.common.util.ASWException; import net.geedge.asw.common.util.RCode; import net.geedge.asw.common.util.T; -import net.geedge.asw.module.app.entity.ApplicationEntity; import net.geedge.asw.module.app.entity.PackageEntity; import net.geedge.asw.module.app.service.IApplicationService; import net.geedge.asw.module.app.service.IPackageService; +import net.geedge.asw.module.environment.entity.EnvironmentEntity; +import net.geedge.asw.module.environment.service.IEnvironmentService; import net.geedge.asw.module.feign.client.KibanaClient; import net.geedge.asw.module.runner.dao.PcapDao; import net.geedge.asw.module.runner.entity.JobEntity; import net.geedge.asw.module.runner.entity.PcapEntity; import net.geedge.asw.module.runner.entity.PlaybookEntity; -import net.geedge.asw.module.runner.entity.RunnerEntity; import net.geedge.asw.module.runner.service.IJobService; import net.geedge.asw.module.runner.service.IPcapService; import net.geedge.asw.module.runner.service.IPlaybookService; -import net.geedge.asw.module.runner.service.IRunnerService; import net.geedge.asw.module.runner.util.PcapParserThread; import net.geedge.asw.module.runner.util.RunnerConstant; import net.geedge.asw.module.workbook.service.IWorkbookResourceService; @@ -68,7 +66,7 @@ public class PcapServiceImpl extends ServiceImpl implements private IJobService jobService; @Autowired - private IRunnerService runnerService; + private IEnvironmentService environmentService; @Autowired private IPlaybookService playbookService; @@ -103,8 +101,8 @@ public class PcapServiceImpl extends ServiceImpl implements if (T.ObjectUtil.isNotNull(job)) { pcap.setJobId(job.getId()); - RunnerEntity runner = runnerService.getById(job.getRunnerId()); - pcap.setRunner(runner); + EnvironmentEntity environment = environmentService.getById(job.getEnvId()); + pcap.setEnvironment(environment); PackageEntity pkg = packageService.getById(job.getPackageId()); pcap.setPkg(pkg); @@ -123,13 +121,6 @@ public class PcapServiceImpl extends ServiceImpl implements return page; } - - @Override - public PcapEntity savePcap(String jobId, Resource fileResource) { - JobEntity job = jobService.getById(jobId); - return this.savePcap(fileResource, job.getTags(), job.getWorkbookId(), job.getWorkspaceId(), job.getCreateUserId()); - } - @Override public PcapEntity savePcap(Resource fileResource, String... params) { String description = T.ArrayUtil.get(params, 0); diff --git a/src/main/java/net/geedge/asw/module/runner/service/impl/RunnerServiceImpl.java b/src/main/java/net/geedge/asw/module/runner/service/impl/RunnerServiceImpl.java index ba205be..b60aecc 100644 --- a/src/main/java/net/geedge/asw/module/runner/service/impl/RunnerServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/runner/service/impl/RunnerServiceImpl.java @@ -1,51 +1,51 @@ -package net.geedge.asw.module.runner.service.impl; - -import cn.dev33.satoken.stp.StpUtil; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import net.geedge.asw.common.util.T; -import net.geedge.asw.module.runner.dao.RunnerDao; -import net.geedge.asw.module.runner.entity.RunnerEntity; -import net.geedge.asw.module.runner.service.IRunnerService; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -@Service -public class RunnerServiceImpl extends ServiceImpl implements IRunnerService { - - @Override - public Page queryList(Map params) { - Page page = T.PageUtil.getPage(params); - List jobList = this.getBaseMapper().queryList(page, params); - page.setRecords(jobList); - return page; - } - - @Override - public RunnerEntity saveRunner(RunnerEntity entity) { - entity.setCreateTimestamp(System.currentTimeMillis()); - entity.setUpdateTimestamp(System.currentTimeMillis()); - entity.setCreateUserId(StpUtil.getLoginIdAsString()); - entity.setUpdateUserId(StpUtil.getLoginIdAsString()); - - // token - entity.setToken(T.IdUtil.fastSimpleUUID()); - - // save - this.save(entity); - return entity; - } - - @Override - public RunnerEntity updateRunner(RunnerEntity entity) { - entity.setUpdateTimestamp(System.currentTimeMillis()); - entity.setUpdateUserId(StpUtil.getLoginIdAsString()); - - // update - this.updateById(entity); - return entity; - } - -} \ No newline at end of file +//package net.geedge.asw.module.runner.service.impl; +// +//import cn.dev33.satoken.stp.StpUtil; +//import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +//import net.geedge.asw.common.util.T; +//import net.geedge.asw.module.runner.dao.RunnerDao; +//import net.geedge.asw.module.runner.entity.RunnerEntity; +//import net.geedge.asw.module.runner.service.IRunnerService; +//import org.springframework.stereotype.Service; +// +//import java.util.List; +//import java.util.Map; +// +//@Service +//public class RunnerServiceImpl extends ServiceImpl implements IRunnerService { +// +// @Override +// public Page queryList(Map params) { +// Page page = T.PageUtil.getPage(params); +// List jobList = this.getBaseMapper().queryList(page, params); +// page.setRecords(jobList); +// return page; +// } +// +// @Override +// public RunnerEntity saveRunner(RunnerEntity entity) { +// entity.setCreateTimestamp(System.currentTimeMillis()); +// entity.setUpdateTimestamp(System.currentTimeMillis()); +// entity.setCreateUserId(StpUtil.getLoginIdAsString()); +// entity.setUpdateUserId(StpUtil.getLoginIdAsString()); +// +// // token +// entity.setToken(T.IdUtil.fastSimpleUUID()); +// +// // save +// this.save(entity); +// return entity; +// } +// +// @Override +// public RunnerEntity updateRunner(RunnerEntity entity) { +// entity.setUpdateTimestamp(System.currentTimeMillis()); +// entity.setUpdateUserId(StpUtil.getLoginIdAsString()); +// +// // update +// this.updateById(entity); +// return entity; +// } +// +//} \ No newline at end of file diff --git a/src/main/resources/db/mapper/runner/JobMapper.xml b/src/main/resources/db/mapper/runner/JobMapper.xml index 381b180..7d16ee8 100644 --- a/src/main/resources/db/mapper/runner/JobMapper.xml +++ b/src/main/resources/db/mapper/runner/JobMapper.xml @@ -7,10 +7,7 @@ - - - - + @@ -25,18 +22,11 @@ - - - - - - - + @@ -55,60 +45,38 @@ pkg.id AS pkg_id, pkg.platform AS pkg_platform, pkg.version AS pkg_version, - pkg.logo AS pkg_logo, - pkg.identifier AS pkg_identifier, + pkg.name AS pkg_name, - app.id AS app_id, - app.name AS app_name, - - run.id AS run_id, - run.name AS run_name, + env.id AS em_id, + env.name AS em_name, pb.id AS pb_id, pb.name AS pb_name FROM job job - LEFT JOIN runner run ON job.runner_id = run.id + LEFT JOIN environment env ON job.env_id = env.id LEFT JOIN package pkg ON job.package_id = pkg.id LEFT JOIN playbook pb ON job.playbook_id = pb.id - LEFT JOIN application app ON pb.app_id = app.id - LEFT JOIN workbook_resource wr ON job.id = wr.resource_id AND wr.resource_type = 'job' job.id in #{id} - - AND app.id in - #{id} - - AND pkg.id in #{id} - - AND run.id in - #{id} + + AND env.id in + #{id} AND pb.id in #{id} - - - AND - locate(#{item}, job.signature_ids) - - - - - AND wr.workbook_id = #{params.workbookId} - - AND job.workspace_id = #{params.workspaceId} @@ -122,26 +90,4 @@ - - - \ No newline at end of file diff --git a/src/main/resources/db/migration/R__AZ_sys_i18n.sql b/src/main/resources/db/migration/R__AZ_sys_i18n.sql index b3af9ed..886415b 100644 --- a/src/main/resources/db/migration/R__AZ_sys_i18n.sql +++ b/src/main/resources/db/migration/R__AZ_sys_i18n.sql @@ -135,6 +135,9 @@ INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_ INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (227, '601004', 'ENVIRONMENT_STATUS_ERROR', '环境状态不可用', 'zh', '', 'admin', 1724030366000); INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (228, '100019', 'SYS_USER_OLDPWD_INCORRECT', 'Incorrect old password. Please try again.', 'en', '', 'admin', 1724030366000); INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (229, '100019', 'SYS_USER_OLDPWD_INCORRECT', '旧密码不正确,请重新输入', 'zh', '', 'admin', 1724030366000); - +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (230, '302002', 'PLAYBOOK_NAME_DUPLICATE', 'playbook name duplicate', 'en', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (231, '302002', 'PLAYBOOK_NAME_DUPLICATE', '剧本名称重复', 'zh', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (232, '601005', 'ENVIRONMENT_ID_CANNOT_EMPTY', 'environment id cannot be empty', 'en', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (233, '601005', 'ENVIRONMENT_ID_CANNOT_EMPTY', '环境 id 不能为空', 'zh', '', 'admin', 1724030366000); SET FOREIGN_KEY_CHECKS = 1; diff --git a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql index ca04c0c..a926916 100644 --- a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql +++ b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql @@ -200,10 +200,8 @@ CREATE TABLE `job` ( `id` varchar(64) NOT NULL COMMENT '主键', `playbook_id` varchar(64) NOT NULL DEFAULT '' COMMENT 'Playbook ID', `package_id` varchar(64) NOT NULL DEFAULT '' COMMENT 'Package ID', - `runner_id` varchar(64) NOT NULL DEFAULT '' COMMENT 'Runner ID', - `schedule_id` varchar(64) NOT NULL DEFAULT '' COMMENT '定时器ID', - `signature_ids` text NOT NULL DEFAULT '' COMMENT '特征ID,多个逗号分隔', - `tags` varchar(256) NOT NULL DEFAULT '' COMMENT '标签; 默认:"";多个用逗号分隔;例:kz,vpn,android', + `env_id` varchar(64) NOT NULL DEFAULT '' COMMENT 'env ID', + `playbook_param` varchar(1024) NOT NULL DEFAULT '' COMMENT 'playbook运行参数', `start_timestamp` bigint(20) NOT NULL DEFAULT -1 COMMENT '开始时间戳', `end_timestamp` bigint(20) NOT NULL DEFAULT -1 COMMENT '结束时间戳', `status` varchar(64) NOT NULL DEFAULT '' COMMENT '状态; 可选值: created,pending,running,passed,failed,cancel', @@ -217,7 +215,7 @@ CREATE TABLE `job` ( PRIMARY KEY (`id`) USING BTREE, KEY `idx_playbook_id` (`playbook_id`) USING BTREE, KEY `idx_package_id` (`package_id`) USING BTREE, - KEY `idx_runner_id` (`runner_id`) USING BTREE, + KEY `idx_env_id` (`env_id`) USING BTREE, KEY `idx_workspace_id` (`workspace_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;