diff --git a/modules/module-ci-machine/pom.xml b/modules/module-ci-machine/pom.xml new file mode 100644 index 00000000..e36adc39 --- /dev/null +++ b/modules/module-ci-machine/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + cd.casic.boot + modules + ${revision} + + + module-ci-machine + + jar + ${revision} + ${project.artifactId} + + + + cd.casic.boot + commons + + + + cd.casic.boot + spring-boot-starter-security + + + com.antherd + sm-crypto + 0.3.2.1-RELEASE + + + diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/contants/MachineErrorCodeConstants.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/contants/MachineErrorCodeConstants.java new file mode 100644 index 00000000..a526d9e5 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/contants/MachineErrorCodeConstants.java @@ -0,0 +1,37 @@ +package cd.casic.module.machine.contants; + +import cd.casic.framework.commons.exception.ErrorCode; + +/** + * 机器报错 + */ +public interface MachineErrorCodeConstants { + // ========== 机器基础信息模块 1-003-000-000 ========== + ErrorCode MACHINE_INFO_NULL = new ErrorCode(1_003_000_000, "机器信息为空"); + ErrorCode MACHINE_INFO_HOST_IP_NULL = new ErrorCode(1_003_000_001, "机器主机IP为空"); + ErrorCode MACHINE_INFO_USER_NAME_NULL = new ErrorCode(1_003_000_002, "机器用户名为空"); + ErrorCode MACHINE_INFO_TYPE_NULL = new ErrorCode(1_003_000_003, "机器类型为空"); + ErrorCode MACHINE_INFO_TYPE_NOT_EXISTS = new ErrorCode(1_003_000_004, "机器类型不存在"); + ErrorCode MACHINE_INFO_TAG_NULL = new ErrorCode(1_003_000_005, "机器唯一标识为空"); + ErrorCode MACHINE_INFO_TAG_EXISTS = new ErrorCode(1_003_000_006, "机器唯一标识已存在"); + ErrorCode MACHINE_INFO_AUTHENTICATION_TYPE_NULL = new ErrorCode(1_003_000_007, "机器认证类型为空"); + ErrorCode MACHINE_INFO_AUTHENTICATION_TYPE_NOT_EXISTS = new ErrorCode(1_003_000_008, "机器认证类型不存在"); + ErrorCode MACHINE_ENABLE = new ErrorCode(1_003_000_009, "机器启用中"); + + // ========== 机器环境变量模块 1-003-002-000 ========== + ErrorCode MACHINE_ENV_NULL = new ErrorCode(1_003_002_000, "机器环境变量为空"); + ErrorCode MACHINE_ENV_NOT_EXISTS = new ErrorCode(1_003_002_001, "机器不存在"); + ErrorCode MACHINE_ENV_KEY_ILLEGAL = new ErrorCode(1_003_002_002, "机器环境变量键不合法"); + + // ========== 机器代理模块 1-003-003-000 ========== + ErrorCode MACHINE_PROXY_HOST_IP_NULL = new ErrorCode(1_003_003_000, "机器代理主机地址为空"); + ErrorCode MACHINE_PROXY_USER_NAME_NULL = new ErrorCode(1_003_003_001, "机器代理用户名为空"); + ErrorCode MACHINE_PROXY_NOT_EXISTS = new ErrorCode(1_003_003_002, "机器代理不存在"); + ErrorCode MACHINE_PROXY_TYPE_NOT_EXISTS = new ErrorCode(1_003_003_003, "机器代理类型不存在"); + ErrorCode MACHINE_PROXY_IS_ONLINE = new ErrorCode(1_003_003_004, "机器代理在线,不能删除"); + + // ========== 密钥模块 1-003-004-000 ========== + ErrorCode SECRET_KEY_NULL = new ErrorCode(1_003_004_000, "密钥为空"); + ErrorCode SECRET_KEY_NOT_EXISTS = new ErrorCode(1_003_004_001, "密钥不存在"); + ErrorCode ENCRYPT_OR_DECRYPT_FAIL = new ErrorCode(1_003_004_002, "加密/解密失败"); +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineEnvController.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineEnvController.java new file mode 100644 index 00000000..d7ca1c20 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineEnvController.java @@ -0,0 +1,84 @@ +package cd.casic.module.machine.controller; + +import cd.casic.framework.commons.pojo.CommonResult; +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.framework.commons.util.object.BeanUtils; +import cd.casic.module.machine.dal.dataobject.MachineEnvDO; +import cd.casic.module.machine.service.MachineEnvService; +import cd.casic.module.machine.controller.vo.MachineEnvVO; +import cn.hutool.core.collection.CollUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import static cd.casic.framework.commons.pojo.CommonResult.success; + +/** + * 环境变量控制器 + */ +@Tag(name = "环境变量管理") +@RestController +@RequestMapping("/ci/machineEnv") +@Validated +public class MachineEnvController { + + @Resource + private MachineEnvService machineEnvService; + + @PostMapping("/create") + @Operation(summary = "新增环境变量") + @PreAuthorize("@ss.hasPermission('ci:machineEnv:create')") + public CommonResult createEnv(@Valid @RequestBody MachineEnvVO machineEnvVO) { + Long id = machineEnvService.createEnv(machineEnvVO); + return success(id); + } + + @PutMapping("/update") + @Operation(summary = "修改环境变量") + @PreAuthorize("@ss.hasPermission('ci:machineEnv:update')") + public CommonResult updateEnv(@Valid @RequestBody MachineEnvVO machineEnvVO) { + machineEnvService.updateEnv(machineEnvVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除机器的环境变量") + @PreAuthorize("@ss.hasPermission('ci:machineEnv:delete')") + public CommonResult deleteEnv(@RequestParam("id") Long id) { + machineEnvService.deleteEnv(id); + return success(true); + } + + @DeleteMapping("/deleteList") + @Operation(summary = "批量删除机器环境变量") + @PreAuthorize("@ss.hasPermission('ci:machineEnv:delete')") + public CommonResult deleteEnvList(@RequestParam("ids") String ids) { + machineEnvService.deleteEnvList(ids); + return success(true); + } + + @GetMapping("/getEnv") + @Operation(summary = "获取机器的环境变量") + public CommonResult getEnv(@RequestParam("id") Long id) { + MachineEnvVO machineEnvVO = machineEnvService.getEnv(id); + return success(machineEnvVO); + } + + + @PostMapping("/list") + @Operation(summary = "获取环境变量列表") + public CommonResult> getEnvPage(@Valid @RequestBody MachineEnvVO machineEnvVO) { + PageResult pageResult = machineEnvService.getEnvPage(machineEnvVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(new PageResult<>(pageResult.getTotal())); + } + return success(BeanUtils.toBean(pageResult, MachineEnvVO.class)); + } +} + diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineInfoController.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineInfoController.java new file mode 100644 index 00000000..e0abd893 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineInfoController.java @@ -0,0 +1,83 @@ +package cd.casic.module.machine.controller; + +import cd.casic.framework.commons.pojo.CommonResult; +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.framework.commons.util.object.BeanUtils; +import cd.casic.module.machine.controller.vo.SecretKeyVO; +import cd.casic.module.machine.dal.dataobject.MachineInfoDO; +import cd.casic.module.machine.service.MachineInfoService; +import cd.casic.module.machine.controller.vo.MachineInfoVO; +import cn.hutool.core.collection.CollUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cd.casic.framework.commons.pojo.CommonResult.success; + +@RestController +@Tag(name = "机器信息管理") +@RequestMapping("/ci/machineInfo") +@Validated +public class MachineInfoController { + @Resource + private MachineInfoService machineInfoService; + + @PostMapping("/create") + @Operation(summary = "新增机器信息") +// @PreAuthorize("@ss.hasPermission('ci:machineInfo:create')") + public CommonResult createMachine(@Valid @RequestBody MachineInfoVO machineInfoVO) { + Long id = machineInfoService.createMachine(machineInfoVO); + return success(id); + } + + @PutMapping("/update") + @Operation(summary = "编辑机器信息") +// @PreAuthorize("@ss.hasPermission('ci:machineInfo:update')") + public CommonResult updateMachineInfo(@Valid @RequestBody MachineInfoVO machineInfoVO) { + machineInfoService.updateMachineInfo(machineInfoVO); + return success(true); + } + + @PutMapping("/updateStatus") + @Operation(summary = "机器启用/停用") +// @PreAuthorize("@ss.hasPermission('ci:machineInfo:status')") + public CommonResult updateStatus(@Valid @RequestBody MachineInfoVO machineInfoVO) { + Integer newStatus = machineInfoService.updateStatus(machineInfoVO); + return success(newStatus); + } + + @PostMapping("/list") + @Operation(summary = "获取机器信息列表") + public CommonResult> list(@Valid @RequestBody MachineInfoVO machineInfoVO) { + PageResult pageResult = machineInfoService.listMachineInfo(machineInfoVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(new PageResult<>(pageResult.getTotal())); + } + return success(BeanUtils.toBean(pageResult, MachineInfoVO.class)); + } + + @DeleteMapping("/delete") + @Operation(summary = "机器信息删除") +// @PreAuthorize("@ss.hasPermission('ci:machineInfo:delete')") + public CommonResult deleteMachineInfo(@RequestParam("machineInfoId") Long machineInfoId) { + machineInfoService.deleteMachineInfo(machineInfoId); + return success(true); + } + + @DeleteMapping("/deleteList") + @Operation(summary = "批量删除机器信息") +// @PreAuthorize("@ss.hasPermission('ci:machineInfo:delete')") + public CommonResult deleteMachineInfoList(@RequestParam("machineInfoIds") String ids) { + machineInfoService.deleteMachineInfoList(ids); + return success(true); + } + + @PutMapping("/bindingSecretKey") + @Operation(summary = "绑定/解绑密钥") + public void bindingSecretKey(@RequestBody SecretKeyVO secretKeyVO) { + machineInfoService.bindingSecretKey(secretKeyVO); + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineProxyController.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineProxyController.java new file mode 100644 index 00000000..83082ee5 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/MachineProxyController.java @@ -0,0 +1,81 @@ +package cd.casic.module.machine.controller; + +import cd.casic.framework.commons.pojo.CommonResult; +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.framework.commons.util.object.BeanUtils; +import cd.casic.module.machine.controller.vo.MachineProxyVO; +import cd.casic.module.machine.dal.dataobject.MachineProxyDO; +import cd.casic.module.machine.service.MachineProxyService; +import cn.hutool.core.collection.CollUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +import static cd.casic.framework.commons.pojo.CommonResult.success; + +/** + * 机器代理控制器 + */ +@RestController +@RequestMapping("/ci/machineProxy") +@Tag(name = "机器代理管理") +@Validated +public class MachineProxyController { + + @Resource + private MachineProxyService machineProxyService; + + @PostMapping("/create") + @Operation(summary = "注册新的机器代理") +// @PreAuthorize("@ss.hasPermission('ci:machineProxy:create')") + public CommonResult createProxy(@Valid @RequestBody MachineProxyVO machineProxyVO) { + Long id = machineProxyService.createProxy(machineProxyVO); + return success(id); + } + + @PutMapping("/update") + @Operation(summary = "修改代理") +// @PreAuthorize("@ss.hasPermission('ci:machineProxy:update')") + public CommonResult updateProxy(@Valid @RequestBody MachineProxyVO machineProxyVO) { + machineProxyService.updateProxy(machineProxyVO); + return success(true); + } + + @PostMapping("/list") + @Operation(summary = "获取代理列表") + public CommonResult> getProxyPage(@Valid @RequestBody MachineProxyVO machineProxyVO) { + PageResult pageResult = machineProxyService.getProxyPage(machineProxyVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(new PageResult<>(pageResult.getTotal())); + } + return success(BeanUtils.toBean(pageResult, MachineProxyVO.class)); + } + + @GetMapping("/allStatus") + @Operation(summary = "获取所有代理的状态统计") + public CommonResult> getStatusStatistics() { + return success(machineProxyService.getAllProxyStatus()); + } + + @DeleteMapping("delete") + @Operation(summary = "删除代理") + public CommonResult delete(@RequestParam("id") Long id) { + machineProxyService.delete(id); + return success(true); + } + + @DeleteMapping("/deleteList") + @Operation(summary = "批量删除代理") +// @PreAuthorize("@ss.hasPermission('ci:machineProxy:delete')") + public CommonResult deleteProxyList(@RequestParam String ids) { + machineProxyService.deleteProxyList(ids); + return success(true); + } + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/SecretKeyController.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/SecretKeyController.java new file mode 100644 index 00000000..1624b1c2 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/SecretKeyController.java @@ -0,0 +1,76 @@ +package cd.casic.module.machine.controller; + +import cd.casic.framework.commons.pojo.CommonResult; +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.framework.commons.util.object.BeanUtils; +import cd.casic.module.machine.dal.dataobject.MachineInfoDO; +import cd.casic.module.machine.dal.dataobject.SecretKeyDO; +import cd.casic.module.machine.service.SecretKeyService; +import cd.casic.module.machine.controller.vo.SecretKeyVO; +import cn.hutool.core.collection.CollUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cd.casic.framework.commons.pojo.CommonResult.success; + +@RestController +@RequestMapping("/ci/secretKey") +@Tag(name = "密钥管理") +@Validated +public class SecretKeyController { + @Resource + private SecretKeyService secretKeyService; + + @PostMapping(value = "/create") + @Operation(summary = "新增密钥") +// @PreAuthorize("@ss.hasPermission('ci:secretKey:create')") + public CommonResult createSecretKey(@Valid @RequestBody SecretKeyVO secretKeyVO) { + Long secretKeyId = secretKeyService.createSecretKey(secretKeyVO); + return success(secretKeyId); + } + + @PutMapping("/update") + @Operation(summary = "编辑密钥信息") +// @PreAuthorize("@ss.hasPermission('ci:secretKey:update')") + public CommonResult updateSecretKey(@Valid @RequestBody SecretKeyVO secretKeyVO) { + secretKeyService.updateSecretKey(secretKeyVO); + return success(true); + } + + @GetMapping("/getBindMachine") + @Operation(summary = "获取密钥绑定的机器列表") + public CommonResult> getBindMachine(@RequestParam Long secretKeyId) { + return success(secretKeyService.getBindMachine(secretKeyId)); + } + + @GetMapping("/getSecretKey") + @Operation(summary = "获取机器的密钥") + public CommonResult getSecretKey(@RequestParam("id") Long id) { + SecretKeyVO secretKeyVO = secretKeyService.getSecretKey(id); + return success(secretKeyVO); + } + + @DeleteMapping("/deleteList") + @Operation(summary = "批量删除密钥") +// @PreAuthorize("@ss.hasPermission('ci:secretKey:delete')") + public CommonResult deleteSecretKeyList(@RequestParam("ids") List ids) { + secretKeyService.deleteSecretKeyList(ids); + return success(true); + } + + @PostMapping("/list") + @Operation(summary = "获取密钥信息列表") + public CommonResult> getSecretKeyPage(@Valid @RequestBody SecretKeyVO secretKeyVO) { + PageResult pageResult = secretKeyService.getSecretKeyPage(secretKeyVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(new PageResult<>(pageResult.getTotal())); + } + return success(BeanUtils.toBean(pageResult, SecretKeyVO.class)); + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/MachineEnvVO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/MachineEnvVO.java new file mode 100644 index 00000000..16ae6eef --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/MachineEnvVO.java @@ -0,0 +1,38 @@ +package cd.casic.module.machine.controller.vo; + +import cd.casic.framework.commons.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +@EqualsAndHashCode(callSuper = true) +@Schema(description = "管理后台 - 机器环境变量信息 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) // 添加链式调用支持 +public class MachineEnvVO extends PageParam { + + @Schema(description = "环境变量ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "环境变量键", requiredMode = Schema.RequiredMode.REQUIRED, example = "JAVA_HOME") + private String envKey; + + @Schema(description = "环境变量值", requiredMode = Schema.RequiredMode.REQUIRED, example = "/usr/java/jdk1.8.0_271") + private String envValue; + + @Schema(description = "环境变量描述", example = "Java运行环境路径") + private String description; + + @Schema(description = "关联的机器ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long machineId; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-06-15T10:30:00") + private LocalDateTime createTime; + + @Schema(description = "更新时间", example = "2023-06-15T10:30:00") + private LocalDateTime updateTime; +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/MachineInfoVO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/MachineInfoVO.java new file mode 100644 index 00000000..beb64176 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/MachineInfoVO.java @@ -0,0 +1,64 @@ +package cd.casic.module.machine.controller.vo; + +import cd.casic.framework.commons.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import lombok.experimental.Accessors; + +import java.util.Date; + +@EqualsAndHashCode(callSuper = true) +@Schema(description = "管理后台 - 机器信息 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class MachineInfoVO extends PageParam { + + @Schema(description = "机器ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-06-15T10:30:00") + private Date createTime; + + @Schema(description = "更新时间", example = "2023-06-15T10:30:00") + private Date updateTime; + + @Schema(description = "机器名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "server-01") + private String name; + + @Schema(description = "机器标签,唯一标识", example = "production,web-server") + private String tag; + + @Schema(description = "主机IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "192.168.1.100") + private String hostIp; + + @Schema(description = "机器描述", example = "生产环境Web服务器") + private String description; + + @Schema(description = "登录用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin") + private String username; + + @Schema(description = "机器状态", example = "online,offline,maintenance") + private Integer status = -1; + + @Schema(description = "SSH端口", example = "22") + private Integer sshPort; + + @Schema(description = "登录密码", example = "******") + private String password; + + @Schema(description = "密钥ID", example = "5") + private Long secretKeyId; + + @Schema(description = "代理ID", example = "101") + private Long machineProxyId; + + @Schema(description = "认证类型", example = "password,key") + private Integer authenticationType ; + + @Schema(description = "机器信息类型", example = "Linux,Windows") + private Integer machineInfoType; + + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/MachineProxyVO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/MachineProxyVO.java new file mode 100644 index 00000000..f8f75259 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/MachineProxyVO.java @@ -0,0 +1,52 @@ +package cd.casic.module.machine.controller.vo; + +import cd.casic.framework.commons.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 机器代理信息 Response VO") +@EqualsAndHashCode(callSuper = true) +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class MachineProxyVO extends PageParam { + + @Schema(description = "代理ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin") + private String username; + + @Schema(description = "代理类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "HTTP") + private Integer proxyType = -1; + + @Schema(description = "版本号", example = "1.0.0") + private String version; + + @Schema(description = "状态(ONLINE:在线,OFFLINE:离线)", requiredMode = Schema.RequiredMode.REQUIRED, example = "ONLINE") + private int status = -1; + + @Schema(description = "描述信息", example = "用于生产环境的代理服务器") + private String description; + + @Schema(description = "主机IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "192.168.1.100") + private String hostIp; + + @Schema(description = "SSH端口", requiredMode = Schema.RequiredMode.REQUIRED, example = "22") + private String sshPort; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-06-15T10:30:00") + private LocalDateTime createTime; + + @Schema(description = "更新时间", example = "2023-06-15T10:30:00") + private LocalDateTime updateTime; + + @Schema(description = "密码", example = "******") + private String password; + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/SecretKeyVO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/SecretKeyVO.java new file mode 100644 index 00000000..00f7171a --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/vo/SecretKeyVO.java @@ -0,0 +1,48 @@ +package cd.casic.module.machine.controller.vo; + +import cd.casic.framework.commons.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; +import java.util.List; + +@EqualsAndHashCode(callSuper = true) +@Schema(description = "管理后台 - 密钥信息 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) // 添加链式调用支持 +public class SecretKeyVO extends PageParam { + + @Schema(description = "密钥ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "密钥名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "生产环境密钥") + private String name; + + @Schema(description = "密钥描述", example = "用于加密敏感数据的密钥") + private String description; + + @Schema(description = "密钥密码", example = "******") + private String password; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-06-15T10:30:00") + private LocalDateTime createTime; + + @Schema(description = "更新时间", example = "2023-06-15T10:30:00") + private LocalDateTime updateTime; + + @Schema(description = "关联的机器ID列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1024, 2048]") + private List machineInfoIds; + + @Schema(description = "私钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "******") + private String privateKey; + + @Schema(description = "公钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "******") + private String publicKey; + + @Schema(description = "绑定/解绑密钥",example = "true") + private Boolean enableBind; +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineEnvDO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineEnvDO.java new file mode 100644 index 00000000..be0abc80 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineEnvDO.java @@ -0,0 +1,57 @@ +package cd.casic.module.machine.dal.dataobject; + + +import cd.casic.framework.commons.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.*; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 环境变量实体类 + */ + +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("machine_env") +public class MachineEnvDO extends BaseDO { + + + /** + * 环境变量id + */ + @TableId + private Long id; + + /** + * 机器ID(唯一关联) + */ + private Long machineId; + + /** + * 环境变量键 + */ + private String envKey; + + /** + * 环境变量值 + */ + private String envValue; + + + /** + * 描述信息 + */ + private String description; + + +} + + + + diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineInfoDO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineInfoDO.java new file mode 100644 index 00000000..3471d23f --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineInfoDO.java @@ -0,0 +1,71 @@ +package cd.casic.module.machine.dal.dataobject; + +import cd.casic.framework.commons.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName(value = "machine_info") +public class MachineInfoDO extends BaseDO { + + /** + * 机器id + */ + @TableId + private Long id; + + + @TableField(value = "name") + private String name; + + /** + * 机器唯一标识 + */ + @TableField(value = "tag") + private String tag; + + @TableField(value = "host_ip") + private String hostIp; + + @TableField(value = "description") + private String description; + + //1:Linux 2:Windows + @TableField(value = "machine_info_type") + private Integer machineInfoType; + + // 1:启用 0:停用 + @TableField(value = "status") + private Integer status; + + //用户名 + @TableField(value = "username") + private String username; + + //SSH端口号 + @TableField(value = "ssh_port") + private Integer sshPort; + + @TableField(value = "password") + private String password; + + @TableField(value = "secret_key_id") + private Long secretKeyId; + + @TableField(value = "machine_proxy_id") + private Long machineProxyId; + + //1:密码认证 2:密钥认证 + @TableField(value = "authentication_type") + private Integer authenticationType; + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineProxyDO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineProxyDO.java new file mode 100644 index 00000000..44008bfa --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/MachineProxyDO.java @@ -0,0 +1,56 @@ +package cd.casic.module.machine.dal.dataobject; + +import cd.casic.framework.commons.dataobject.BaseDO; +import cd.casic.module.machine.enums.MachineProxyStatus; +import com.baomidou.mybatisplus.annotation.*; +import cd.casic.module.machine.enums.MachineProxyType; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + * 机器代理实体类 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("machine_proxy") +public class MachineProxyDO extends BaseDO { + + /** + * 代理id + */ + @TableId + private Long id; + + @TableField(value = "host_ip") + private String hostIp; + + @TableField(value = "ssh_port") + private String sshPort; + + @TableField(value = "proxy_type") + private int proxyType; + + @TableField(value = "version") + private String version; + + @TableField(value = "status") + private int status; + + @TableField(value = "username") + private String username; + + @TableField(value = "password") + private String password; + + @TableField(value = "description") + private String description; + + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/SecretKeyDO.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/SecretKeyDO.java new file mode 100644 index 00000000..cc271b50 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/dataobject/SecretKeyDO.java @@ -0,0 +1,44 @@ +package cd.casic.module.machine.dal.dataobject; + +import cd.casic.framework.commons.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName(value = "machine_secret_key") +public class SecretKeyDO extends BaseDO { + + /** + * 密钥id + */ + @TableId + private Long id; + + @TableField(value = "name") + private String name; + + @TableField(value = "description") + private String description; + + + //密钥密码 + @TableField(value = "password") + private String password; + +// @TableField(value = "public_key") + private String publicKey; + + +// @TableField(value = "private_key") + private String privateKey; + + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/model/Keypair.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/model/Keypair.java new file mode 100644 index 00000000..3a58737a --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/model/Keypair.java @@ -0,0 +1,26 @@ +package cd.casic.module.machine.dal.model; + +/** + * 基于SM2的秘钥对 + * (本项目中配置的,自己使用可根据自己的需求进行更换) + * + */ +public class Keypair { + + /** + * 公钥 + */ + public static String PUBLIC_KEY = "04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54"; + + /** + * 私钥 + */ + public static String PRIVATE_KEY = "3037723d47292171677ec8bd7dc9af696c7472bc5f251b2cec07e65fdef22e25"; + + /** + * SM4的对称秘钥(生产环境需要改成自己使用的) + * 16 进制字符串,要求为 128 比特 + */ + public static String KEY = "0123456789abcdeffedcba9876543210"; + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/MachineEnvMapper.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/MachineEnvMapper.java new file mode 100644 index 00000000..b5060c25 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/MachineEnvMapper.java @@ -0,0 +1,27 @@ +package cd.casic.module.machine.dal.mysql; + +import cd.casic.framework.mybatis.core.mapper.BaseMapperX; +import cd.casic.module.machine.controller.vo.MachineEnvVO; +import cd.casic.module.machine.dal.dataobject.MachineEnvDO; +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.framework.mybatis.core.query.LambdaQueryWrapperX; +import org.apache.ibatis.annotations.Mapper; + +import java.time.LocalDateTime; + +/** + * 环境变量Mapper接口 + */ +@Mapper +public interface MachineEnvMapper extends BaseMapperX { + default PageResult selectPage(MachineEnvVO machineEnvVO) { + LambdaQueryWrapperX machineEnvDOLambdaQueryWrapperX = new LambdaQueryWrapperX() + .likeIfPresent(MachineEnvDO::getEnvKey, machineEnvVO.getEnvKey()) + .likeIfPresent(MachineEnvDO::getDescription, machineEnvVO.getDescription()); + if (machineEnvVO.getMachineId() != null && machineEnvVO.getMachineId() > 0) { + machineEnvDOLambdaQueryWrapperX.eqIfPresent(MachineEnvDO::getMachineId, machineEnvVO.getMachineId()); + } + return selectPage(machineEnvVO, machineEnvDOLambdaQueryWrapperX); + } + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/MachineInfoMapper.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/MachineInfoMapper.java new file mode 100644 index 00000000..1f3f2013 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/MachineInfoMapper.java @@ -0,0 +1,56 @@ +package cd.casic.module.machine.dal.mysql; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.framework.mybatis.core.mapper.BaseMapperX; +import cd.casic.framework.mybatis.core.query.LambdaQueryWrapperX; +import cd.casic.module.machine.controller.vo.MachineInfoVO; +import cd.casic.module.machine.dal.dataobject.MachineInfoDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface MachineInfoMapper extends BaseMapperX { + default Boolean existsByTag(String tag) { + return selectOne(new QueryWrapper().eq("tag", tag)) != null; + } + + default void updateStatus(Long machineInfoId, Integer status) { + UpdateWrapper set = new UpdateWrapper<>(); + set.eq("id", machineInfoId).set("status", status); + this.update(null, set); + } + + default void bindingSecretKey(List machineInfoIds, Long secretKeyId,Boolean enableBind) { + UpdateWrapper wrapper = new UpdateWrapper<>(); + wrapper.in("id", machineInfoIds); + if (enableBind){ + wrapper.set("secret_key_id", secretKeyId);// 匹配 ID 集合 + }else { + wrapper.set("secret_key_id", null); + } + this.update(null, wrapper); + } + + default PageResult selectPage(MachineInfoVO machineInfoVO) { + LambdaQueryWrapperX machineInfoDOLambdaQueryWrapperX = new LambdaQueryWrapperX() + .likeIfPresent(MachineInfoDO::getName, machineInfoVO.getName()) + .likeIfPresent(MachineInfoDO::getTag, machineInfoVO.getTag()) + .likeIfPresent(MachineInfoDO::getDescription, machineInfoVO.getDescription()) + .likeIfPresent(MachineInfoDO::getUsername, machineInfoVO.getUsername()) + .likeIfPresent(MachineInfoDO::getHostIp, machineInfoVO.getHostIp()); + if (machineInfoVO.getStatus() != -1) { + machineInfoDOLambdaQueryWrapperX.eqIfPresent(MachineInfoDO::getStatus, machineInfoVO.getStatus()); + } + return selectPage(machineInfoVO, machineInfoDOLambdaQueryWrapperX); + } + + default List selectBindMachineBySecretKey(Long secretKeyId) { + LambdaQueryWrapperX lambdaQueryWrapperX = new LambdaQueryWrapperX() + .eq(MachineInfoDO::getSecretKeyId, secretKeyId); + return selectList(lambdaQueryWrapperX); + } + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/MachineProxyMapper.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/MachineProxyMapper.java new file mode 100644 index 00000000..05e4df4a --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/MachineProxyMapper.java @@ -0,0 +1,29 @@ +package cd.casic.module.machine.dal.mysql; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.framework.mybatis.core.mapper.BaseMapperX; +import cd.casic.framework.mybatis.core.query.LambdaQueryWrapperX; +import cd.casic.module.machine.controller.vo.MachineProxyVO; +import cd.casic.module.machine.dal.dataobject.MachineProxyDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 机器代理Mapper接口 + */ +@Mapper +public interface MachineProxyMapper extends BaseMapperX { + + default PageResult selectPage(MachineProxyVO machineProxyVO) { + LambdaQueryWrapperX machineProxyDOLambdaQueryWrapperX = new LambdaQueryWrapperX() + .eqIfPresent(MachineProxyDO::getHostIp, machineProxyVO.getHostIp()) + .likeIfPresent(MachineProxyDO::getDescription, machineProxyVO.getDescription()); + if (machineProxyVO.getStatus() != -1) { + machineProxyDOLambdaQueryWrapperX.eqIfPresent(MachineProxyDO::getStatus, machineProxyVO.getStatus()); + } + if (machineProxyVO.getProxyType() != -1) { + machineProxyDOLambdaQueryWrapperX.eqIfPresent(MachineProxyDO::getProxyType, machineProxyVO.getProxyType()); + } + return selectPage(machineProxyVO, machineProxyDOLambdaQueryWrapperX); + } + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/SecretKeyMapper.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/SecretKeyMapper.java new file mode 100644 index 00000000..bb530946 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/mysql/SecretKeyMapper.java @@ -0,0 +1,18 @@ +package cd.casic.module.machine.dal.mysql; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.framework.mybatis.core.mapper.BaseMapperX; +import cd.casic.framework.mybatis.core.query.LambdaQueryWrapperX; +import cd.casic.module.machine.controller.vo.SecretKeyVO; +import cd.casic.module.machine.dal.dataobject.SecretKeyDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SecretKeyMapper extends BaseMapperX { + //查询列表 + default PageResult selectPage(SecretKeyVO secretKeyVO) { + return selectPage(secretKeyVO, new LambdaQueryWrapperX() + .likeIfPresent(SecretKeyDO::getName, secretKeyVO.getName()) + .likeIfPresent(SecretKeyDO::getDescription, secretKeyVO.getDescription())); + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/AuthenticationType.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/AuthenticationType.java new file mode 100644 index 00000000..71f8314c --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/AuthenticationType.java @@ -0,0 +1,25 @@ +package cd.casic.module.machine.enums; + + +import cd.casic.framework.commons.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum AuthenticationType implements IntArrayValuable { + PASSWORD(1,"密码认证"), + SECRET_KEY(2,"密钥认证"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AuthenticationType::getCode).toArray(); + private final int code; + + private final String message; + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineInfoStatus.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineInfoStatus.java new file mode 100644 index 00000000..d0ddd5b1 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineInfoStatus.java @@ -0,0 +1,24 @@ +package cd.casic.module.machine.enums; + + +import cd.casic.framework.commons.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum MachineInfoStatus implements IntArrayValuable { + ENABLE(1, "启用"), + UN_ENABLE(0, "停用"); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MachineInfoStatus::getCode).toArray(); + private final int code; + + private final String message; + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineInfoType.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineInfoType.java new file mode 100644 index 00000000..2a168b31 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineInfoType.java @@ -0,0 +1,24 @@ +package cd.casic.module.machine.enums; + + +import cd.casic.framework.commons.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum MachineInfoType implements IntArrayValuable { + Linux(1,"Linux"), + WINDOWS(2,"Windows"); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MachineInfoType::getCode).toArray(); + private final int code; + + private final String message; + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineProxyStatus.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineProxyStatus.java new file mode 100644 index 00000000..e162c82a --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineProxyStatus.java @@ -0,0 +1,33 @@ +package cd.casic.module.machine.enums; + + +import cd.casic.framework.commons.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.List; + +@Getter +@AllArgsConstructor +public enum MachineProxyStatus implements IntArrayValuable { + /** + * 代理状态 (online, offline, installing, updating, error) + */ + ONLINE(1, "online"), + OFFLINE(2, "offline"), + INSTALLING(3, "installing"), + UPDATING(4, "updating"), + ERROR(5, "error"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MachineProxyStatus::getCode).toArray(); + + private final int code; + + private final String message; + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineProxyType.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineProxyType.java new file mode 100644 index 00000000..88171c5f --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/MachineProxyType.java @@ -0,0 +1,31 @@ +package cd.casic.module.machine.enums; + +import cd.casic.framework.commons.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum MachineProxyType implements IntArrayValuable { + HTTP(1, "http"), + SOCKS4(2, "socks4"), + SOCKS5(3, "socks5"); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MachineProxyType::getCode).toArray(); + + /** + * 状态值 + */ + private final Integer code; + /** + * 状态名 + */ + private final String message; + + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineEnvService.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineEnvService.java new file mode 100644 index 00000000..1222ff42 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineEnvService.java @@ -0,0 +1,45 @@ +package cd.casic.module.machine.service; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.module.machine.controller.vo.MachineEnvVO; +import cd.casic.module.machine.dal.dataobject.MachineEnvDO; +import jakarta.validation.Valid; + +/** + * 环境变量服务接口 + */ + +public interface MachineEnvService { + /** + * 创建或更新机器的环境变量(一对一关系) + */ + Long createEnv(@Valid MachineEnvVO machineEnvVO); + + /** + * 删除机器的环境变量 + */ + void deleteEnv(Long machineEvnId); + + /** + * 获取机器的环境变量 + * + * @param machineId 机器ID + * @return 环境变量DTO + */ + MachineEnvVO getEnv(Long machineId); + + /** + * @return 环境变量列表 + */ + PageResult getEnvPage(@Valid MachineEnvVO machineEnvVO); + + /** + * 批量删除 + */ + void deleteEnvList(String ids); + + /* + * 修改环境变量 + */ + void updateEnv(@Valid MachineEnvVO machineEnvVO); +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineInfoService.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineInfoService.java new file mode 100644 index 00000000..23c1f5d0 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineInfoService.java @@ -0,0 +1,69 @@ +package cd.casic.module.machine.service; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.module.machine.controller.vo.MachineInfoVO; +import cd.casic.module.machine.controller.vo.SecretKeyVO; +import cd.casic.module.machine.dal.dataobject.MachineInfoDO; +import jakarta.validation.Valid; + +import java.util.List; + +public interface MachineInfoService { + /** + * 新增机器 + * + * @return 新增机器的id + */ + Long createMachine(MachineInfoVO MachineInfoVO); + + /** + * 查看机器列表 + * + * @return 机器列表 + */ + PageResult listMachineInfo(@Valid MachineInfoVO MachineInfoVO); + + /** + * 更新机器信息 + */ + void updateMachineInfo(@Valid MachineInfoVO machineInfoVO); + + /** + * 变更机器状态 + */ + Integer updateStatus(@Valid MachineInfoVO machineInfoVO); + + /** + * 绑定密钥 + */ + void bindingSecretKey(SecretKeyVO secretKeyVO); + + /** + * 批量删除机器 + * + * @param machineInfoIds 机器id列表 + */ + void deleteMachineInfoList(String machineInfoIds); + + /** + * 删除机器信息 + * + * @param machineInfoId 机器id + */ + void deleteMachineInfo(Long machineInfoId); + + /** + * 获取绑定的密钥 + * + * @param secretKeyId 密钥id + * @return 绑定的机器列表 + */ + List selectBindMachineBySecretKey(Long secretKeyId); + + /** + * 验证机器是否存在 + * + * @param id 机器id + */ + MachineInfoDO validateMachineInfoExists(Long id); +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineProxyService.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineProxyService.java new file mode 100644 index 00000000..9dd8beb5 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/MachineProxyService.java @@ -0,0 +1,49 @@ +package cd.casic.module.machine.service; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.module.machine.controller.vo.MachineProxyVO; +import cd.casic.module.machine.dal.dataobject.MachineProxyDO; +import jakarta.validation.Valid; + +import java.util.Map; + +/** + * 机器代理服务接口 + */ +public interface MachineProxyService { + /** + * 注册新的机器代理 + */ + Long createProxy(@Valid MachineProxyVO machineProxyVO); + + /** + * 更新代理状态 + */ + void updateProxy(@Valid MachineProxyVO machineProxyVO); + + /** + * 删除代理 + * + */ + void delete(Long id); + + /** + * 获取所有代理的状态统计 + * + * @return 状态统计Map + */ + Map getAllProxyStatus(); + + + /** + * 批量删除代理 + * + * @param proxyIds 代理ID列表 + */ + void deleteProxyList(String proxyIds); + + /** + * 获取代理列表(分页) + */ + PageResult getProxyPage(@Valid MachineProxyVO machineProxyVO); +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/SecretKeyService.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/SecretKeyService.java new file mode 100644 index 00000000..19326057 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/SecretKeyService.java @@ -0,0 +1,48 @@ +package cd.casic.module.machine.service; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.module.machine.dal.dataobject.MachineInfoDO; +import cd.casic.module.machine.dal.dataobject.SecretKeyDO; +import cd.casic.module.machine.controller.vo.SecretKeyVO; +import jakarta.validation.Valid; + +import java.util.List; + +public interface SecretKeyService { + /** + * 新增密钥 + */ + Long createSecretKey(@Valid SecretKeyVO secretKeyVO); + + /** + * 更新密钥 + */ + void updateSecretKey(@Valid SecretKeyVO secretKeyVO); + + /** + * 获取密钥列表(分页) + */ + PageResult getSecretKeyPage(@Valid SecretKeyVO secretKeyVO); + + /** + * 批量删除密钥 + * @param ids 密钥id集合 + */ + void deleteSecretKeyList(List ids); + + /** + * 根据id获取密钥对象 + */ + SecretKeyVO getSecretKey(Long id); + + /** + * 获取绑定的密钥的机器列表 + */ + List getBindMachine(Long secretKeyId); + + /** + * 获取公钥内容 + */ + String getPublicKeyContent(Long secretKeyId); +} + diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineEnvServiceImpl.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineEnvServiceImpl.java new file mode 100644 index 00000000..3363307e --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineEnvServiceImpl.java @@ -0,0 +1,105 @@ +package cd.casic.module.machine.service.impl; + +import cd.casic.module.machine.controller.vo.MachineEnvVO; +import cd.casic.module.machine.dal.dataobject.MachineEnvDO; +import cd.casic.module.machine.dal.mysql.MachineEnvMapper; +import cd.casic.module.machine.service.MachineEnvService; +import cd.casic.framework.commons.pojo.PageResult; +import com.google.common.annotations.VisibleForTesting; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import cd.casic.framework.commons.util.object.BeanUtils; + +import java.util.Arrays; +import java.util.List; + +import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; +import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; + +/** + * 环境变量服务实现类 + */ +@Service("machineEnvService") +public class MachineEnvServiceImpl implements MachineEnvService { + + @Resource + private MachineEnvMapper machineEnvMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createEnv(MachineEnvVO machineEnvVO) { + validateMachineEnvAdd(machineEnvVO); + // 检查键是否合法 + validateKey(machineEnvVO.getEnvKey()); + MachineEnvDO machineEnvDO = BeanUtils.toBean(machineEnvVO, MachineEnvDO.class); + machineEnvMapper.insert(machineEnvDO); + return machineEnvDO.getId(); + } + + @Override + public void deleteEnv(Long machineEvnId) { + machineEnvMapper.deleteById(machineEvnId); + } + + + @Override + public MachineEnvVO getEnv(Long machineId) { + MachineEnvDO machineEnvDO = validateMachineEnvExists(machineId); + return BeanUtils.toBean(machineEnvDO, MachineEnvVO.class); + } + + + @Override + public PageResult getEnvPage(MachineEnvVO machineEnvVO) { + return machineEnvMapper.selectPage(machineEnvVO); + } + + @Override + public void deleteEnvList(String ids) { + //ids转换为List,使用流 + List machineEnvIds = Arrays.stream(ids.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .map(Long::parseLong) + .toList(); + + machineEnvMapper.deleteBatchIds(machineEnvIds); + } + + @Override + public void updateEnv(MachineEnvVO machineEnvVO) { + MachineEnvDO machineEnvDO = validateMachineEnvExists(machineEnvVO.getId()); + BeanUtils.copyProperties(machineEnvVO, machineEnvDO); + machineEnvMapper.updateById(machineEnvDO); + } + + @VisibleForTesting + MachineEnvDO validateMachineEnvExists(Long id) { + if (id == null) { + return null; + } + MachineEnvDO machineEnvDO = machineEnvMapper.selectById(id); + if (machineEnvDO == null) { + throw exception(MACHINE_ENV_NOT_EXISTS); + } + return machineEnvDO; + } + + @VisibleForTesting + void validateMachineEnvAdd(MachineEnvVO machineEnvVO) { + if (machineEnvVO.getEnvKey() == null || machineEnvVO.getEnvValue() == null) { + throw exception(MACHINE_ENV_NULL); + } + } + + + // 检查环境变量键是否合法 + @VisibleForTesting + private void validateKey(String key) { + if (!key.matches("^[a-zA-Z_][a-zA-Z0-9_]*$")) { + throw exception(MACHINE_ENV_KEY_ILLEGAL); + } + } + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineInfoServiceImpl.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineInfoServiceImpl.java new file mode 100644 index 00000000..90428a99 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineInfoServiceImpl.java @@ -0,0 +1,176 @@ +package cd.casic.module.machine.service.impl; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.module.machine.controller.vo.SecretKeyVO; +import cd.casic.module.machine.enums.AuthenticationType; +import cd.casic.module.machine.enums.MachineInfoType; +import cd.casic.module.machine.dal.mysql.MachineInfoMapper; +import cd.casic.module.machine.controller.vo.MachineInfoVO; +import cd.casic.module.machine.dal.dataobject.MachineInfoDO; +import cd.casic.module.machine.enums.MachineInfoStatus; +import cd.casic.module.machine.service.MachineInfoService; +import cd.casic.module.machine.service.SecretKeyService; +import com.google.common.annotations.VisibleForTesting; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import cd.casic.framework.commons.util.object.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; + +import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; +import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; + +/** + * 机器信息服务实现类 + */ +@Slf4j +@Service("machineInfoToService") +public class MachineInfoServiceImpl implements MachineInfoService { + + @Resource + private SecretKeyService secretKeyService; + + @Resource + private MachineInfoMapper machineInfoMapper; + + @Override + public Long createMachine(MachineInfoVO machineInfoVO) { + validateMachineEnvAdd(machineInfoVO); + validateMachineTagUnique(machineInfoVO.getTag()); + MachineInfoDO machineInfoDO = BeanUtils.toBean(machineInfoVO, MachineInfoDO.class); + if (machineInfoVO.getAuthenticationType() == 2) { + Long secretKeyId = machineInfoDO.getSecretKeyId(); + SecretKeyVO secretKey = secretKeyService.getSecretKey(secretKeyId); + if (secretKey == null) { + throw exception(SECRET_KEY_NOT_EXISTS); + } + } + machineInfoMapper.insert(machineInfoDO); + return machineInfoDO.getId(); + } + + @Override + public void updateMachineInfo(MachineInfoVO machineInfoVO) { + validateMachineEnvAdd(machineInfoVO); + String newTag = machineInfoVO.getTag(); + MachineInfoDO machineInfoDO = validateMachineInfoExists(machineInfoVO.getId()); + String oldTag = machineInfoDO.getTag(); + if (!newTag.equals(oldTag)) { + validateMachineTagUnique(newTag); + } + BeanUtils.copyProperties(machineInfoVO, machineInfoDO); + machineInfoMapper.updateById(machineInfoDO); + } + + @Override + public Integer updateStatus(MachineInfoVO machineInfoVO) { + machineInfoMapper.updateStatus(machineInfoVO.getId(), machineInfoVO.getStatus()); + return machineInfoVO.getStatus(); + } + + @Override + public PageResult listMachineInfo(MachineInfoVO machineInfoVO) { + return machineInfoMapper.selectPage(machineInfoVO); + } + + @Override + public void bindingSecretKey(SecretKeyVO secretKeyVO) { + machineInfoMapper.bindingSecretKey(secretKeyVO.getMachineInfoIds(), secretKeyVO.getId(), secretKeyVO.getEnableBind()); + } + + @Override + @Transactional//其中一个在线,那么就回滚 + public void deleteMachineInfoList(String machineInfoIds) { + List machineInfoIdList = Arrays.stream(machineInfoIds.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .map(Long::parseLong) + .toList(); + machineInfoIdList.forEach(this::deleteMachineInfo); + } + + @Override + public void deleteMachineInfo(Long machineInfoId) { + MachineInfoDO machineInfoDO = validateMachineInfoExists(machineInfoId); + validateMachineEnable(machineInfoDO); + machineInfoMapper.deleteById(machineInfoId); + } + + @Override + public List selectBindMachineBySecretKey(Long secretKeyId) { + return machineInfoMapper.selectBindMachineBySecretKey(secretKeyId); + } + + @VisibleForTesting + void validateMachineEnvAdd(MachineInfoVO machineInfoVO) { + if (machineInfoVO.getHostIp().isEmpty()) { + throw exception(MACHINE_INFO_HOST_IP_NULL); + } + if (machineInfoVO.getUsername().isEmpty()) { + throw exception(MACHINE_INFO_USER_NAME_NULL); + } + if (machineInfoVO.getTag().isEmpty()) { + throw exception(MACHINE_INFO_TAG_NULL); + } + + if (machineInfoVO.getAuthenticationType() != null) { + boolean flag = true; + for (int type : AuthenticationType.ARRAYS) { + if (type == machineInfoVO.getAuthenticationType()) { + flag = false; + break; + } + } + if (flag) { + throw exception(MACHINE_INFO_AUTHENTICATION_TYPE_NOT_EXISTS); + } + } else { + throw exception(MACHINE_INFO_AUTHENTICATION_TYPE_NULL); + } + + + if (machineInfoVO.getMachineInfoType() != null) { + boolean flag = true; + for (int type : MachineInfoType.ARRAYS) { + if (type == machineInfoVO.getMachineInfoType()) { + flag = false; + break; + } + } + if (flag) { + throw exception(MACHINE_INFO_TYPE_NOT_EXISTS); + } + } else { + throw exception(MACHINE_INFO_TYPE_NULL); + } + + } + + @VisibleForTesting + void validateMachineTagUnique(String tag) { + if (machineInfoMapper.existsByTag(tag)) { + throw exception(MACHINE_INFO_TAG_EXISTS); + } + } + + @Override + public MachineInfoDO validateMachineInfoExists(Long id) { + if (id == null) { + throw exception(MACHINE_INFO_NULL); + } + MachineInfoDO machineInfoDO = machineInfoMapper.selectById(id); + if (machineInfoDO == null) { + throw exception(MACHINE_INFO_NULL); + } + return machineInfoDO; + } + + @VisibleForTesting + void validateMachineEnable(MachineInfoDO machineInfoDO) { + if (machineInfoDO.getStatus() == MachineInfoStatus.ENABLE.getCode()) { + throw exception(MACHINE_ENABLE); + } + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineProxyServiceImpl.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineProxyServiceImpl.java new file mode 100644 index 00000000..84bd5e2e --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/MachineProxyServiceImpl.java @@ -0,0 +1,131 @@ +package cd.casic.module.machine.service.impl; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.module.machine.controller.vo.MachineProxyVO; +import cd.casic.module.machine.dal.dataobject.MachineProxyDO; +import cd.casic.module.machine.enums.MachineProxyStatus; +import cd.casic.module.machine.enums.MachineProxyType; +import cd.casic.module.machine.dal.mysql.MachineProxyMapper; +import cd.casic.module.machine.service.MachineProxyService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.annotations.VisibleForTesting; +import jakarta.annotation.Resource; +import cd.casic.framework.commons.util.object.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; +import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; +import static com.baomidou.mybatisplus.extension.toolkit.Db.save; + +/** + * 机器代理服务实现类 + */ +@Service("machineProxyService") +public class MachineProxyServiceImpl implements MachineProxyService { + @Resource + private MachineProxyMapper machineProxyMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createProxy(MachineProxyVO machineProxyVO) { + validateMachineProxyAdd(machineProxyVO); + // 创建代理记录 + MachineProxyDO machineProxyDO = BeanUtils.toBean(machineProxyVO, MachineProxyDO.class); + save(machineProxyDO); + return machineProxyDO.getId(); + } + + @Override + public void updateProxy(MachineProxyVO machineProxyVO) { + // 参数校验 + MachineProxyDO machineProxyDO = validateMachineProxyExists(machineProxyVO.getId()); + // 更新状态 + BeanUtils.copyProperties(machineProxyVO, machineProxyDO); + machineProxyMapper.updateById(machineProxyDO); + } + + @Override + public void delete(Long id) { + MachineProxyDO machineProxyDO = validateMachineProxyExists(id); + validateMachineProxyOnline(machineProxyDO); + machineProxyMapper.deleteById(id); + } + + @VisibleForTesting + void validateMachineProxyOnline(MachineProxyDO machineProxyDO) { + if (machineProxyDO.getStatus() == MachineProxyStatus.ONLINE.getCode()) { + throw exception(MACHINE_PROXY_IS_ONLINE); + } + } + + @Override + public Map getAllProxyStatus() { + List proxyList = machineProxyMapper.selectList(new QueryWrapper<>()); + if (CollectionUtils.isEmpty(proxyList)) { + return Collections.emptyMap(); + } + return proxyList.stream() + .map(MachineProxyDO::getStatus) + .collect(Collectors.groupingBy( + Function.identity(), + // 统计每个分组的元素数量 + Collectors.counting() + )); + } + + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteProxyList(String ids) { + if (ids == null) { + return; + } + List machineProxyIds = Arrays.stream(ids.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .map(Long::parseLong) + .toList(); + // 批量逻辑删除 + machineProxyIds.forEach(this::delete); + } + + @Override + public PageResult getProxyPage(MachineProxyVO machineProxyVO) { + return machineProxyMapper.selectPage(machineProxyVO); + } + + @VisibleForTesting + MachineProxyDO validateMachineProxyExists(Long id) { + if (id == null) { + throw exception(MACHINE_PROXY_NOT_EXISTS); + } + MachineProxyDO machineProxyDO = machineProxyMapper.selectById(id); + if (machineProxyDO == null) { + throw exception(MACHINE_PROXY_NOT_EXISTS); + } + return machineProxyDO; + } + + @VisibleForTesting + void validateMachineProxyAdd(MachineProxyVO machineProxyVO) { + if (machineProxyVO.getHostIp() == null) { + throw exception(MACHINE_PROXY_HOST_IP_NULL); + } + if (machineProxyVO.getUsername() == null) { + throw exception(MACHINE_PROXY_USER_NAME_NULL); + } + + // 校验代理类型 + int[] arrays = MachineProxyType.ARRAYS; + if (Arrays.stream(arrays).filter(i -> i == machineProxyVO.getProxyType()).findAny().isEmpty()) { + throw exception(MACHINE_PROXY_TYPE_NOT_EXISTS); + } + } + +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/SecretKeyServiceImpl.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/SecretKeyServiceImpl.java new file mode 100644 index 00000000..b322a954 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/SecretKeyServiceImpl.java @@ -0,0 +1,111 @@ +package cd.casic.module.machine.service.impl; + +import cd.casic.framework.commons.pojo.PageResult; +import cd.casic.framework.commons.util.object.BeanUtils; +import cd.casic.module.machine.controller.vo.SecretKeyVO; +import cd.casic.module.machine.dal.dataobject.MachineInfoDO; +import cd.casic.module.machine.dal.dataobject.SecretKeyDO; +import cd.casic.module.machine.dal.mysql.SecretKeyMapper; +import cd.casic.module.machine.service.MachineInfoService; +import cd.casic.module.machine.service.SecretKeyService; +import cd.casic.module.machine.utils.CryptogramUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.google.common.annotations.VisibleForTesting; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.script.ScriptException; +import java.util.List; +import java.util.Objects; + +import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception; +import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*; + +/** + * 密钥服务实现类 + */ +@Service("secretKeyService") +public class SecretKeyServiceImpl implements SecretKeyService { + + @Resource + private MachineInfoService machineInfoService; + + @Resource + private SecretKeyMapper secretKeyMapper; + + @Override + public SecretKeyVO getSecretKey(Long id) { + SecretKeyDO secretKeyDO = validateSecretKeyExists(id); + return BeanUtils.toBean(secretKeyDO, SecretKeyVO.class); + } + + @Override + public List getBindMachine(Long secretKeyId) { + return machineInfoService.selectBindMachineBySecretKey(secretKeyId); + } + + @Override + public String getPublicKeyContent(Long secretKeyId) { + return secretKeyMapper.selectById(secretKeyId).getPublicKey(); + } + + @Override + public Long createSecretKey(SecretKeyVO secretKeyVO) { + validateSecretKeyAdd(secretKeyVO); + SecretKeyDO secretKeyDO = BeanUtils.toBean(secretKeyVO, SecretKeyDO.class); + try { + //密码加密 + secretKeyDO.setPassword(CryptogramUtil.doEncrypt(secretKeyVO.getPassword())); + //公钥加密 + secretKeyDO.setPublicKey(CryptogramUtil.doEncrypt(secretKeyVO.getPublicKey())); + } catch (ScriptException e) { + throw exception(ENCRYPT_OR_DECRYPT_FAIL); + } + secretKeyMapper.insert(secretKeyDO); + return secretKeyDO.getId(); + } + + @Override + public void updateSecretKey(SecretKeyVO secretKeyVO) { + SecretKeyDO secretKeyDO = validateSecretKeyExists(secretKeyVO.getId()); + BeanUtils.copyProperties(secretKeyVO, secretKeyDO); + secretKeyMapper.updateById(secretKeyDO); + } + + @Override + @Transactional + public void deleteSecretKeyList(List ids) { + SecretKeyVO secretKeyVO = new SecretKeyVO() + .setMachineInfoIds(ids) + .setEnableBind(false); + machineInfoService.bindingSecretKey(secretKeyVO); + secretKeyMapper.deleteBatchIds(ids); + } + + @Override + public PageResult getSecretKeyPage(SecretKeyVO secretKeyVO) { + return secretKeyMapper.selectPage(secretKeyVO, new LambdaQueryWrapper() + .like(Objects.nonNull(secretKeyVO.getName()), SecretKeyDO::getName, secretKeyVO.getName()) + .like(Objects.nonNull(secretKeyVO.getDescription()), SecretKeyDO::getDescription, secretKeyVO.getDescription())); + } + + @VisibleForTesting + void validateSecretKeyAdd(SecretKeyVO secretKeyVO) { + if (secretKeyVO == null) { + throw exception(SECRET_KEY_NULL); + } + } + + @VisibleForTesting + SecretKeyDO validateSecretKeyExists(Long id) { + if (id == null) { + throw exception(SECRET_KEY_NOT_EXISTS); + } + SecretKeyDO secretKeyDO = secretKeyMapper.selectById(id); + if (secretKeyDO == null) { + throw exception(SECRET_KEY_NOT_EXISTS); + } + return secretKeyDO; + } +} diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/utils/CryptogramUtil.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/utils/CryptogramUtil.java new file mode 100644 index 00000000..0a91bfd1 --- /dev/null +++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/utils/CryptogramUtil.java @@ -0,0 +1,111 @@ +package cd.casic.module.machine.utils; + +import cd.casic.module.machine.dal.model.Keypair; +import cn.hutool.log.Log; +import com.antherd.smcrypto.sm2.Sm2; +import com.antherd.smcrypto.sm3.Sm3; +import com.antherd.smcrypto.sm4.Sm4; +import com.antherd.smcrypto.sm4.Sm4Options; + +import javax.script.ScriptException; + +public class CryptogramUtil { + + private static final Log log = Log.get(); + + /** + * 加密方法(Sm2 的专门针对前后端分离,非对称秘钥对的方式,暴露出去的公钥,对传输过程中的密码加个密) + * + * @param str 待加密数据 + * @return 加密后的密文 + * @author yubaoshan + */ + public static String doSm2Encrypt(String str) throws ScriptException { + return Sm2.doEncrypt(str, Keypair.PUBLIC_KEY); + } + + /** + * 解密方法 + * 如果采用加密机的方法,用try catch 捕捉异常,返回原文值即可 + * + * @param str 密文 + * @return 解密后的明文 + * @author yubaoshan + */ + public static String doSm2Decrypt(String str) throws ScriptException { + // 解密 + return Sm2.doDecrypt(str, Keypair.PRIVATE_KEY); + } + + /** + * 加密方法 + * + * @param str 待加密数据 + * @return 加密后的密文 + * @author yubaoshan + */ + public static String doEncrypt(String str) throws ScriptException { + // SM4 加密 cbc模式 + Sm4Options sm4Options4 = new Sm4Options(); + sm4Options4.setMode("cbc"); + sm4Options4.setIv("fedcba98765432100123456789abcdef"); + return Sm4.encrypt(str, Keypair.KEY, sm4Options4); + } + + /** + * 解密方法 + * 如果采用加密机的方法,用try catch 捕捉异常,返回原文值即可 + * + * @param str 密文 + * @return 解密后的明文 + * @author yubaoshan + */ + public static String doDecrypt(String str) throws ScriptException { + // 解密,cbc 模式,输出 utf8 字符串 + Sm4Options sm4Options8 = new Sm4Options(); + sm4Options8.setMode("cbc"); + sm4Options8.setIv("fedcba98765432100123456789abcdef"); + String docString = Sm4.decrypt(str, Keypair.KEY, sm4Options8); + if (docString.isEmpty()) { + log.warn(">>> 字段解密失败,返回原文值:{}", str); + return str; + } else { + return docString; + } + } + + /** + * 纯签名 + * + * @param str 待签名数据 + * @return 签名结果 + * @author yubaoshan + */ + public static String doSignature(String str) throws ScriptException { + return Sm2.doSignature(str, Keypair.PRIVATE_KEY); + } + + /** + * 验证签名结果 + * + * @param originalStr 签名原文数据 + * @param str 签名结果 + * @return 是否通过 + * @author yubaoshan + */ + public static boolean doVerifySignature(String originalStr, String str) throws ScriptException { + return Sm2.doVerifySignature(originalStr, str, Keypair.PUBLIC_KEY); + } + + /** + * 通过杂凑算法取得hash值,用于做数据完整性保护 + * + * @param str 字符串 + * @return hash 值 + * @author yubaoshan + */ + public static String doHashValue(String str) throws ScriptException { + return Sm3.sm3(str); + } + +} diff --git a/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/StageController.java b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/StageController.java index 980a0c57..faafb1ae 100644 --- a/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/StageController.java +++ b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/StageController.java @@ -77,7 +77,7 @@ public class StageController { */ @PostMapping(path="/deleteTasksOrStage/{taskId}") public CommonResult deleteTasksOrStage(@NotNull@PathVariable String taskId){ - stageService.deleteStagesOrTask(taskId); + stageService.deleteStagesAndTask(taskId); return CommonResult.success(); } /** diff --git a/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateManagerController.java b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateManagerController.java index 06f019b1..2570fcab 100644 --- a/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateManagerController.java +++ b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateManagerController.java @@ -1,6 +1,7 @@ package cd.casic.ci.api; +import cd.casic.ci.process.dto.req.template.TemplateCreateReq; import cd.casic.ci.process.dto.req.template.TemplateQueryReq; import cd.casic.ci.process.dto.resp.template.TemplateFindResp; import cd.casic.ci.process.process.dataObject.base.BaseIdReq; @@ -31,32 +32,11 @@ public class TemplateManagerController { @Resource private TemplateManagerService templateManagerService; -// @PostMapping(path="/createTemplate") -// public CommonResult createTemplate(@RequestBody @Valid TemplateCreateReq req){ -// -// String templateId = templateManagerService.createTemplate(req); -// -// return CommonResult.success(templateId); -// } -// -// -// @PostMapping(path="/deletePipeline") -// public CommonResult deletePipeline(@RequestBody @Valid PipelineReq req){ -// -// templateManagerService.deletePipeline(req); -// -// return CommonResult.success(); -// } -// -// -// @PostMapping(path="/updatePipeline") -// public CommonResult updatePipeline(@RequestBody @NotNull @Valid PipelineUpdateReq pipeline){ -// -// templateManagerService.updatePipeline(pipeline); -// -// return CommonResult.success(); -// } - + @PostMapping(path="/createTemplate") + public CommonResult createTemplate(@RequestBody @Valid TemplateCreateReq req){ + String templateId = templateManagerService.createTemplateManager(req); + return CommonResult.success(templateId); + } @PostMapping(path="/findTemplatePage") public CommonResult> findTemplatePage(@RequestBody @NotNull @Valid TemplateQueryReq query){ diff --git a/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateStageController.java b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateStageController.java new file mode 100644 index 00000000..b4797356 --- /dev/null +++ b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateStageController.java @@ -0,0 +1,129 @@ +package cd.casic.ci.api; + + +import cd.casic.ci.process.dto.req.stage.StageCreateReq; +import cd.casic.ci.process.dto.req.stage.StageUpdateReq; +import cd.casic.ci.process.dto.req.template.TemplateStageCreateReq; +import cd.casic.ci.process.dto.req.template.TemplateStageUpdateReq; +import cd.casic.ci.process.dto.resp.context.SingletonRunContextResp; +import cd.casic.ci.process.dto.resp.stage.StageResp; +import cd.casic.ci.process.dto.resp.template.TemplateStageResp; +import cd.casic.ci.process.process.dataObject.template.TemplateStage; +import cd.casic.ci.process.process.service.stage.StageService; +import cd.casic.ci.process.process.service.template.TemplateStageService; +import cd.casic.framework.commons.pojo.CommonResult; +import jakarta.annotation.Resource; +import jakarta.annotation.security.PermitAll; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * @pi.protocol: http + * @pi.groupName: 流水线多阶段控制器 + */ +@RestController +@RequestMapping("/templateStage") +public class TemplateStageController { + + @Resource + private TemplateStageService stageService; + + /** + * @pi.name:创建流水线阶段及任务 + * @pi.path:/stage/createStage + * @pi.methodType:post + * @pi.request-type:json + * @pi.param: model=stage + */ + @PostMapping(path="/createStage") + public CommonResult createStagesOrTask(@RequestBody TemplateStageCreateReq stage){ + String taskId = stageService.createStagesOrTask(stage); + return CommonResult.success(taskId); + } + + /** + * @pi.name:查询流水线阶段信息 + * @pi.path:/stage/finAllStage + * @pi.methodType:post + * @pi.request-type: formdata + * @pi.param: name=pipelineId;dataType=string;value=pipelineId; + */ + @PermitAll + @PostMapping(path="/findAllStage/{templateId}") + public CommonResult> findAllPipelineTaskOrTask(@NotNull @PathVariable String templateId){ + List stageRespList = stageService.findAllStagesTask(templateId); + return CommonResult.success(stageRespList); + } + + /** + * @pi.name:更新流水线阶段任务名称Or移动流水线阶段 + * @pi.path:/stage/createStage + * @pi.methodType:post + * @pi.request-type:json + * @pi.param: model=stage + */ + @PostMapping(path="/updateStage") + public CommonResult updateStageTask(@RequestBody @Valid @NotNull TemplateStageUpdateReq stage){ + stageService.updateStagesTask(stage); + return CommonResult.success(); + } + + /** + * @pi.name:删除流水线阶段及任务 + * @pi.path:/stage/deleteStage + * @pi.methodType:post + * @pi.request-type: formdata + * @pi.param: name=taskId;dataType=string;value=taskId; + */ + @PostMapping(path="/deleteTasksOrStage/{taskId}") + public CommonResult deleteTasksOrStage(@NotNull@PathVariable String taskId){ + stageService.deleteStagesAndTask(taskId); + return CommonResult.success(); + } +// /** +// * 复制stage节点 +// * */ +// @PostMapping(path="/copyStage/{stageId}") +// public CommonResult copyStage(@NotEmpty@PathVariable String stageId){ +// stageService.copyStage(stageId); +// return CommonResult.success(); +// } + @PostMapping("/deleteFirstStage/{stageId}") + public CommonResult deleteFirstStage(@PathVariable String stageId){ + stageService.deleteFirstStage(stageId); + return CommonResult.success(); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateTasksController.java b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateTasksController.java new file mode 100644 index 00000000..5b99c508 --- /dev/null +++ b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TemplateTasksController.java @@ -0,0 +1,46 @@ +package cd.casic.ci.api; + + +import cd.casic.ci.process.dto.req.task.TaskUpdateReq; +import cd.casic.ci.process.dto.req.template.TemplateTaskUpdateReq; +import cd.casic.ci.process.dto.resp.task.TasksResp; +import cd.casic.ci.process.dto.resp.template.TemplateTasksResp; +import cd.casic.ci.process.process.service.task.TaskService; +import cd.casic.ci.process.process.service.template.TemplateTaskService; +import cd.casic.framework.commons.pojo.CommonResult; +import jakarta.annotation.Resource; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/templateTask") +public class TemplateTasksController { + @Resource + private TemplateTaskService taskService; + /** + * @pi.name:查询任务及任务详情 + * @pi.path:/tasks/findOneTasksOrTask + * @pi.methodType:post + * @pi.request-type: formdata + * @pi.param: name=taskId;dataType=string;value=taskId; + */ + @PostMapping(path="/findOneTasksOrTask/{taskId}") + public CommonResult findOneTasksOrTask(@NotNull @PathVariable String taskId){ + return CommonResult.success(taskService.getRespById(taskId)); + } +// /** +// * 复制task节点 +// * */ +// @PostMapping(path="/copyTask/{taskId}") +// public CommonResult copyTask(@NotEmpty @PathVariable String taskId){ +// taskService.copyTask(taskId); +// return CommonResult.success(); +// } + @PostMapping(path="/updateTask") + public CommonResult updateTask(@RequestBody TemplateTaskUpdateReq req){ + Boolean b = taskService.updateTask(req); + return CommonResult.success(b); + } + +} diff --git a/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TestCaseManagerController.java b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TestCaseManagerController.java index 6b77e5fb..7c2ba034 100644 --- a/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TestCaseManagerController.java +++ b/modules/module-ci-process-api/src/main/java/cd/casic/ci/api/TestCaseManagerController.java @@ -3,19 +3,21 @@ package cd.casic.ci.api; import cd.casic.ci.process.dto.req.testCase.TestCaseManagerQueryReq; import cd.casic.ci.process.dto.req.testCase.TestCaseManagerReq; +import cd.casic.ci.process.dto.resp.testCase.TestCaseManagerDownloadResp; import cd.casic.ci.process.dto.resp.testCase.TestCaseManagerResp; import cd.casic.ci.process.process.dataObject.base.BaseIdReq; import cd.casic.ci.process.process.service.testCase.TestCaseManagerService; import cd.casic.framework.commons.pojo.CommonResult; import cd.casic.framework.commons.pojo.PageResult; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.SftpException; import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import org.jetbrains.annotations.NotNull; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import java.io.IOException; import java.util.List; /** @@ -83,5 +85,8 @@ public class TestCaseManagerController { return CommonResult.success(resp); } - + @GetMapping("/downLoadById") + public CommonResult downLoadByManagerId(@RequestParam String managerId){ + return CommonResult.success(testCaseManagerService.downLoadById(managerId)); + } } diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/constant/PipelineTargetTypeConstant.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/constant/PipelineTargetTypeConstant.java new file mode 100644 index 00000000..e7499b99 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/constant/PipelineTargetTypeConstant.java @@ -0,0 +1,17 @@ +package cd.casic.ci.process.constant; + +import lombok.Getter; + +@Getter +public class PipelineTargetTypeConstant { + public static final String SOURCE_CODE="SOURCE_CODE"; + public static final String BIN="BIN"; + public static final String FIRM_WARE="FIRM_WARE"; + public static final String WEB_SITE="WEB_SITE"; + + private final String msg; + + PipelineTargetTypeConstant(String msg) { + this.msg = msg; + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateCreateReq.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateCreateReq.java index edf15f59..f0bd6258 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateCreateReq.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateCreateReq.java @@ -12,4 +12,18 @@ import lombok.Data; @Data public class TemplateCreateReq{ + /** + * 模板名称 + */ + private String templateName; + + /** + * 模板分类 + */ + private String templateType; + + /** + * 描述 + */ + private String remark; } diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateStageCreateReq.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateStageCreateReq.java new file mode 100644 index 00000000..8fe3c438 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateStageCreateReq.java @@ -0,0 +1,13 @@ +package cd.casic.ci.process.dto.req.template; + +import cd.casic.ci.process.dto.req.task.TaskCreateReq; +import lombok.Data; + +@Data +public class TemplateStageCreateReq { + // 阶段stageId + private String stageId; + // 如果需要新增阶段则传这个 + private Integer stageSort; + private TemplateTaskCreateReq task; +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateStageUpdateReq.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateStageUpdateReq.java new file mode 100644 index 00000000..b410fd6d --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateStageUpdateReq.java @@ -0,0 +1,13 @@ +package cd.casic.ci.process.dto.req.template; + +import lombok.Data; + +@Data +public class TemplateStageUpdateReq { + // 更新名称 + private String stageName; + // 更新sort + private Integer stageSort; + private String id; + private String pipelineId; +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateTaskCreateReq.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateTaskCreateReq.java new file mode 100644 index 00000000..1138245b --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateTaskCreateReq.java @@ -0,0 +1,16 @@ +package cd.casic.ci.process.dto.req.template; + +import lombok.Data; + +import java.util.Map; + +@Data +public class TemplateTaskCreateReq { + // 第二级stageId,如果没有值则新建第二级stage + private String stageId; + private String taskName; + private String templateId; + private String taskType; + private Integer taskSort; + private Map taskProperties; +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateTaskUpdateReq.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateTaskUpdateReq.java new file mode 100644 index 00000000..f5d0293e --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/req/template/TemplateTaskUpdateReq.java @@ -0,0 +1,14 @@ +package cd.casic.ci.process.dto.req.template; + +import lombok.Data; + +import java.util.Map; + +@Data +public class TemplateTaskUpdateReq { + // 第二级stageId,如果没有值则新建第二级stage + private String id; + private String taskName; + private String taskType; + private Map taskProperties; +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/resp/testCase/TestCaseInfoResp.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/resp/testCase/TestCaseInfoResp.java index a58dbb2e..b81ef46b 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/resp/testCase/TestCaseInfoResp.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/resp/testCase/TestCaseInfoResp.java @@ -22,6 +22,8 @@ public class TestCaseInfoResp { // 测试文件地址(存储路径或URL) private String testFileList; + private String testFilePath; + // 描述信息 private String remark; diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/resp/testCase/TestCaseManagerDownloadResp.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/resp/testCase/TestCaseManagerDownloadResp.java new file mode 100644 index 00000000..8e536cef --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/dto/resp/testCase/TestCaseManagerDownloadResp.java @@ -0,0 +1,9 @@ +package cd.casic.ci.process.dto.resp.testCase; + +import lombok.Data; + +@Data +public class TestCaseManagerDownloadResp { + private String fileName; + private String file; +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/DBFuzzTestingWorker.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/DBFuzzTestingWorker.java index 859f257b..4abf432f 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/DBFuzzTestingWorker.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/DBFuzzTestingWorker.java @@ -3,10 +3,9 @@ package cd.casic.ci.process.engine.worker; import cd.casic.ci.process.common.WorkAtom; import cd.casic.ci.process.engine.runContext.TaskRunContext; import cd.casic.ci.process.engine.worker.base.BaseWorker; -import cd.casic.ci.process.process.dataObject.base.PipBaseElement; -import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; + /** * 数据库模糊测试 * */ @@ -17,9 +16,99 @@ public class DBFuzzTestingWorker extends BaseWorker { @Override public void execute(TaskRunContext context) { - PipBaseElement contextDef = context.getContextDef(); - String id = contextDef.getId(); - log.info("==============触发worker执行========"); - log.info("==========运行context:{}===========", JSON.toJSONString(context)); +// PipBaseElement contextDef = context.getContextDef(); +// String id = contextDef.getId(); +// log.info("==============触发worker执行========"); +// log.info("==========运行context:{}===========", JSON.toJSONString(context)); +// int statusCode = -1; +// +// String login = "http://192.168.100.100:10200/oauth/token"; +// String create = "http://192.168.100.100:10200/api/fuzz/add"; +// String control = "http://192.168.100.100:10200/api/fuzz/control"; +// String getTestDetail = "http://192.168.100.100:10200/api/fuzz/getTestDetail"; +// String genReport = "http://192.168.100.100:10200/api/fuzz/genReport"; +//// static String = "http://192.168.100.100:10200/api/fuzz/add"; +// PipelineNodeConfigInfo nodeConfigInfo = workerParam.getPipelineNodeConfigInfo(); +// String taskId = workerParam.getPipelineLogger().getUuid(); +// NodeLogger nodeLogger = nodeLoggerThreadLocal.get(); +// +// try { +// log.info("attr : {}", nodeConfigInfo.getInfo()); +// log.info("节点信息:" + nodeConfigInfo.getInfo()); +// //将节点的配置信息反编译成对象 +// DbTestConfigInfo dbTestConfigInfo = JSON.parseObject(nodeConfigInfo.getInfo(), DbTestConfigInfo.class); +// HashMap hashMap = new HashMap<>(); +// hashMap.put("code", "f258d8cc7585bc71a10e9f9edba017f7"); +// hashMap.put("grant_type", "client_code"); +// hashMap.put("client_id", "client"); +// HttpResponse logRes = HttpRequest.post(login) +// .form(hashMap)/*.header(Header.CONTENT_TYPE, String.valueOf(ContentType.APPLICATION_JSON))*/.execute(); +// log.info(String.valueOf(logRes.isOk())); +// if (!logRes.isOk()) { +// nodeLogger.appendNow("获取token失败"); +// } +// JSONObject loginJson = JSONObject.parseObject(logRes.body()); +// String accessToken = loginJson.get("access_token").toString(); +// nodeLogger.appendNow("authorize success\n"); +// nodeLogger.appendNow("access_token is " + accessToken); +//// 2、 create project +// JSONObject jsonObject = new JSONObject(); +// jsonObject.put("node", dbTestConfigInfo.getNode()); +// jsonObject.put("engineType", "1"); +// jsonObject.put("taskId", taskId); +// jsonObject.put("taskParams", ""); +// jsonObject.put("taskName", dbTestConfigInfo.getTaskName()); +// HttpResponse createRes = HttpRequest.post(create) +// .body(String.valueOf(jsonObject)).bearerAuth(accessToken).execute(); +// if (!createRes.isOk()) { +// nodeLogger.appendNow("创建项目失败"); +// return String.valueOf(statusCode); +// } +// JSONObject taskjson = JSONObject.parseObject(createRes.body()); +// nodeLogger.appendNow("create project success\n"); +// nodeLogger.appendNow("project taskId is " + taskId); +//// 3、 启动停止测试 +// JSONObject controlObject = new JSONObject(); +// controlObject.put("taskId", taskId); +// // 1 start other stop +// controlObject.put("code", 1); +// HttpResponse controlRes = HttpRequest.post(control) +// .body(String.valueOf(controlObject)).bearerAuth(accessToken).execute(); +// log.info(String.valueOf(controlRes.isOk())); +// if (!controlRes.isOk()) { +// nodeLogger.appendNow("启动项目失败"); +// return String.valueOf(statusCode); +// +// } +// JSONObject controlJson = JSONObject.parseObject(createRes.body()); +// nodeLogger.appendNow("control start success\n"); +// nodeLogger.appendNow("control start code is " + controlJson.get("data\n")); +//// 4、 获取测试详情保存历史数据 +// HashMap haap = new HashMap<>(); +// haap.put("taskId", taskId); +// HttpResponse testDetail = HttpRequest.get(getTestDetail) +// .form(haap).bearerAuth(accessToken).execute(); +// if (!testDetail.isOk()) { +// nodeLogger.appendNow("获取测试详情失败"); +// return String.valueOf(statusCode); +// } +// JSONObject testDetailBody = JSONObject.parseObject(testDetail.body()); +// log.info(testDetailBody.toString()); +// FuzzDbTest fuzzDbTest = new FuzzDbTest(); +// fuzzDbTest.setNodeUuid(nodeConfigInfo.getNodeUuid()); +// fuzzDbTest.setTaskId(taskId); +// fuzzDbTestService.save(fuzzDbTest); +// statusCode = 0; +// } catch (Exception e) { +// String errorMessage = "该节点配置信息为空,请先配置该节点信息" + "\r\n"; +// errorHandle(e, errorMessage); +// } +// +// if (statusCode == 0) { +// log.info("{}节点执行完成", getName()); +// } else { +// log.error("{}节点执行失败", getName()); +// } +// return String.valueOf(statusCode); } } diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/DIYImageExecuteCommandWorker.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/DIYImageExecuteCommandWorker.java index e9241a0a..3fdf041d 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/DIYImageExecuteCommandWorker.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/DIYImageExecuteCommandWorker.java @@ -24,7 +24,6 @@ import java.util.Map; */ @Slf4j @WorkAtom(taskType = "CUSTOM_IMAGE_EXECUTION_COMMAND") -//@Plugin(taskType = "testSSH") public class DIYImageExecuteCommandWorker extends SshWorker { @Override diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/TestGitWorker.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetBinWorker.java similarity index 74% rename from modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/TestGitWorker.java rename to modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetBinWorker.java index 876d6778..5de0ba0b 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/TestGitWorker.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetBinWorker.java @@ -1,17 +1,18 @@ -package cd.casic.ci.process.engine.worker; +package cd.casic.ci.process.engine.worker.target; import cd.casic.ci.process.common.WorkAtom; import cd.casic.ci.process.engine.runContext.TaskRunContext; import cd.casic.ci.process.engine.worker.base.BaseWorker; +import cd.casic.ci.process.constant.PipelineTargetTypeConstant; import cd.casic.ci.process.process.dataObject.base.PipBaseElement; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; @Slf4j -@WorkAtom(taskType = "Github") -public class TestGitWorker extends BaseWorker { +@WorkAtom(taskType = PipelineTargetTypeConstant.BIN) +public class TargetBinWorker extends BaseWorker { @Override diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/TestWorker.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetFirmWareWorker.java similarity index 73% rename from modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/TestWorker.java rename to modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetFirmWareWorker.java index 1425d8ae..68721f24 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/TestWorker.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetFirmWareWorker.java @@ -1,17 +1,18 @@ -package cd.casic.ci.process.engine.worker; +package cd.casic.ci.process.engine.worker.target; import cd.casic.ci.process.common.WorkAtom; import cd.casic.ci.process.engine.runContext.TaskRunContext; import cd.casic.ci.process.engine.worker.base.BaseWorker; +import cd.casic.ci.process.constant.PipelineTargetTypeConstant; import cd.casic.ci.process.process.dataObject.base.PipBaseElement; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; @Slf4j -@WorkAtom(taskType = "GIT") -public class TestWorker extends BaseWorker { +@WorkAtom(taskType = PipelineTargetTypeConstant.FIRM_WARE) +public class TargetFirmWareWorker extends BaseWorker { @Override diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/TargetHandleWorker.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetSourceCodeWorker.java similarity index 92% rename from modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/TargetHandleWorker.java rename to modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetSourceCodeWorker.java index 4481cf6a..4cbb8433 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/TargetHandleWorker.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetSourceCodeWorker.java @@ -1,9 +1,10 @@ -package cd.casic.ci.process.engine.worker; +package cd.casic.ci.process.engine.worker.target; import cd.casic.ci.process.common.WorkAtom; import cd.casic.ci.process.engine.runContext.TaskRunContext; import cd.casic.ci.process.engine.worker.base.BaseWorker; +import cd.casic.ci.process.constant.PipelineTargetTypeConstant; import cd.casic.ci.process.process.service.machine.MachineInfoService; import cd.casic.ci.process.process.service.target.TargetVersionService; import jakarta.annotation.Resource; @@ -14,8 +15,8 @@ import lombok.extern.slf4j.Slf4j; * * */ @Slf4j -@WorkAtom(taskType = "code") -public class TargetHandleWorker extends BaseWorker { +@WorkAtom(taskType = PipelineTargetTypeConstant.SOURCE_CODE) +public class TargetSourceCodeWorker extends BaseWorker { @Resource private TargetVersionService targetVersionService; @Resource diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetWebSiteWorker.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetWebSiteWorker.java new file mode 100644 index 00000000..bb352961 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/target/TargetWebSiteWorker.java @@ -0,0 +1,14 @@ +package cd.casic.ci.process.engine.worker.target; + +import cd.casic.ci.process.common.WorkAtom; +import cd.casic.ci.process.engine.runContext.TaskRunContext; +import cd.casic.ci.process.engine.worker.base.BaseWorker; +import cd.casic.ci.process.constant.PipelineTargetTypeConstant; + +@WorkAtom(taskType = PipelineTargetTypeConstant.WEB_SITE) +public class TargetWebSiteWorker extends BaseWorker { + @Override + public void execute(TaskRunContext context) { + + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/enums/PiplineTargetTypeEnum.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/enums/PiplineTargetTypeEnum.java deleted file mode 100644 index 366adbb2..00000000 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/enums/PiplineTargetTypeEnum.java +++ /dev/null @@ -1,29 +0,0 @@ -package cd.casic.ci.process.enums; - -import lombok.Getter; - -import java.util.HashMap; -import java.util.Map; - -@Getter -public enum PiplineTargetTypeEnum { - SOURCE_CODE("1","源程序"), - BIN("2","二进制"), - FIRM_WARE("3","二进制"), - WEB_SITE("4","web网站") - ; - private final String code; - private final String msg; - - PiplineTargetTypeEnum(String code, String msg) { - this.code = code; - this.msg = msg; - } - public static Map getCodeMap(){ - Map map = new HashMap<>(); - for (PiplineTargetTypeEnum value : values()) { - map.put(value.code, value); - } - return map; - } -} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TargetVersionConverter.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TargetVersionConverter.java index c1e4a40c..0e7dc1a8 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TargetVersionConverter.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TargetVersionConverter.java @@ -29,6 +29,7 @@ public interface TargetVersionConverter { void updateReqCopyToTargetVersion(TargetVersionUpdateReq req,@MappingTarget TargetVersion targetVersion); TargetVersion targetCreateReqToTargetVersionBean(TargetManagerCreateReq req); + TargetVersionCreateReq targetCreateReqToTargetVersionCreateReq(TargetManagerCreateReq req); TargetVersion versionCreateReqToTargetVersionBean(TargetVersionCreateReq req); } diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateConverter.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateConverter.java index 114e6667..1621a1a8 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateConverter.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateConverter.java @@ -1,5 +1,6 @@ package cd.casic.ci.process.process.converter; +import cd.casic.ci.process.dto.req.template.TemplateCreateReq; import cd.casic.ci.process.dto.resp.template.TemplateFindResp; import cd.casic.ci.process.dto.resp.template.TemplateStageResp; import cd.casic.ci.process.dto.resp.template.TemplateTasksResp; @@ -27,5 +28,5 @@ public interface TemplateConverter { PipStage respToStage(TemplateStageResp resp); TemplateStageResp stageTemplateToResp(TemplateStage stage); PipTask templateTaskToTask(TemplateTasksResp resp); - + TemplateManager managerCreateReqToManager(TemplateCreateReq req); } diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateStageConverter.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateStageConverter.java new file mode 100644 index 00000000..f83aeb9a --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateStageConverter.java @@ -0,0 +1,18 @@ +package cd.casic.ci.process.process.converter; + +import cd.casic.ci.process.dto.resp.stage.StageResp; +import cd.casic.ci.process.dto.resp.template.TemplateStageResp; +import cd.casic.ci.process.process.dataObject.stage.PipStage; +import cd.casic.ci.process.process.dataObject.template.TemplateStage; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper(componentModel = "spring") +public interface TemplateStageConverter { + TemplateStageConverter INSTANCE = Mappers.getMapper(TemplateStageConverter.class); + public TemplateStageResp converter(TemplateStage stage); + public List converter(List stage); + +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateTaskConverter.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateTaskConverter.java new file mode 100644 index 00000000..9bfc1181 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/converter/TemplateTaskConverter.java @@ -0,0 +1,14 @@ +package cd.casic.ci.process.process.converter; + +import cd.casic.ci.process.dto.resp.task.TasksResp; +import cd.casic.ci.process.dto.resp.template.TemplateTasksResp; +import cd.casic.ci.process.process.dataObject.task.PipTask; +import cd.casic.ci.process.process.dataObject.template.TemplateTask; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper(componentModel = "spring") +public interface TemplateTaskConverter { + TemplateTaskConverter INSTANCE = Mappers.getMapper(TemplateTaskConverter.class); + TemplateTasksResp doToResp(TemplateTask task); +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/target/TargetVersion.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/target/TargetVersion.java index a5939a1d..6eda8472 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/target/TargetVersion.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/target/TargetVersion.java @@ -46,4 +46,8 @@ public class TargetVersion extends PipBaseElement { * 文件地址路径 */ private String filePath; + /** + * 目标版本构成成分 + * */ + private String versionCompose; } diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/template/TemplateManager.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/template/TemplateManager.java index 9faeadb8..c26200c4 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/template/TemplateManager.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/template/TemplateManager.java @@ -25,16 +25,6 @@ public class TemplateManager extends PipBaseElement { */ private String templateType; - /** - * 模板编码 - */ - private String templateCode; - - /** - * 排序 - */ - private Integer sort; - /** * 描述 */ diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/stage/StageService.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/stage/StageService.java index 6e0e1c39..7035ab23 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/stage/StageService.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/stage/StageService.java @@ -31,10 +31,12 @@ public interface StageService extends IService { List findAllFirstStagesAndChild(String pipelineId); /** - * 删除阶段及任务 + * 删除阶段及任务,如果当前节点是当前阶段最后一个节点, + * 会自动删除阶段 + * * @param taskId 配置id */ - void deleteStagesOrTask(String taskId); + void deleteStagesAndTask(String taskId); /** * 删除流水线所有阶段 diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/stage/impl/StageServiceImpl.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/stage/impl/StageServiceImpl.java index 056e8e75..dd011eb0 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/stage/impl/StageServiceImpl.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/stage/impl/StageServiceImpl.java @@ -189,7 +189,7 @@ public class StageServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) - public void deleteStagesOrTask(String taskId) { + public void deleteStagesAndTask(String taskId) { PipTask taskQuery = new PipTask(); taskQuery.setId(taskId); List taskList = taskService.getTask(taskQuery); diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/target/impl/TargetManagerServiceImpl.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/target/impl/TargetManagerServiceImpl.java index 283df5bb..e7dd38f6 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/target/impl/TargetManagerServiceImpl.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/target/impl/TargetManagerServiceImpl.java @@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.web.multipart.MultipartFile; @@ -77,11 +78,12 @@ public class TargetManagerServiceImpl extends ServiceImpl wrapper = new QueryWrapper<>(); wrapper.eq("version",targetVersion.getVersion()); wrapper.eq("target_id",targetVersion.getTargetId()); - if (!ObjectUtils.isEmpty(targetVersionDao.selectList(wrapper))){ + if (!CollectionUtils.isEmpty(targetVersionDao.selectList(wrapper))){ throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"版本已存在"); } @@ -291,4 +293,7 @@ public class TargetManagerServiceImpl extends ServiceImpl { -// String createTemplate(@Valid TemplateCreateReq req); -// -// void deletePipeline(@Valid PipelineReq req); -// -// void updatePipeline(@Valid PipelineUpdateReq pipeline); -// -// void pipelineClone(@Valid PipelineReq req); -// -// TreeRunContextResp getPipelineRunState(String pipelineId); + String createTemplateManager(TemplateCreateReq req); PageResult findTemplatePage(@Valid TemplateQueryReq query); diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/TemplateStageService.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/TemplateStageService.java new file mode 100644 index 00000000..91fba9ef --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/TemplateStageService.java @@ -0,0 +1,43 @@ +package cd.casic.ci.process.process.service.template; + +import cd.casic.ci.process.dto.req.stage.StageCreateReq; +import cd.casic.ci.process.dto.req.stage.StageUpdateReq; +import cd.casic.ci.process.dto.req.template.TemplateStageCreateReq; +import cd.casic.ci.process.dto.req.template.TemplateStageUpdateReq; +import cd.casic.ci.process.dto.resp.stage.StageResp; +import cd.casic.ci.process.dto.resp.template.TemplateStageResp; +import cd.casic.ci.process.process.dataObject.stage.PipStage; +import cd.casic.ci.process.process.dataObject.template.TemplateStage; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.constraints.NotEmpty; + +import java.util.List; + +public interface TemplateStageService extends IService { + /** + * 创建阶段及关联任务 + * @param stage 阶段信息 + * @return 阶段id + */ + String createStagesOrTask(TemplateStageCreateReq stage); + + + /** + * 查询所有阶段任务 + * @param templateId 流水线id + * @return 任务 + */ + List findAllStagesTask(String templateId); + List findAllFirstStagesAndChild(String templateId); + + + + void deleteFirstStage(String stageId); + /** + * 删除阶段及任务 + * @param taskId 配置id + */ + void deleteStagesAndTask(String taskId); + + public void updateStagesTask(TemplateStageUpdateReq stage); +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/TemplateTaskService.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/TemplateTaskService.java new file mode 100644 index 00000000..2a4ee024 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/TemplateTaskService.java @@ -0,0 +1,24 @@ +package cd.casic.ci.process.process.service.template; + +import cd.casic.ci.process.dto.req.task.TaskUpdateReq; +import cd.casic.ci.process.dto.req.template.TemplateTaskUpdateReq; +import cd.casic.ci.process.dto.resp.task.TasksResp; +import cd.casic.ci.process.dto.resp.template.TemplateTasksResp; +import cd.casic.ci.process.process.dataObject.task.PipTask; +import cd.casic.ci.process.process.dataObject.template.TemplateTask; +import cd.casic.ci.process.util.WebFrameworkUtils; +import cd.casic.framework.commons.exception.ServiceException; +import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants; +import com.baomidou.mybatisplus.extension.service.IService; +import org.apache.commons.lang3.StringUtils; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +public interface TemplateTaskService extends IService { + List getTask(TemplateTask pipTask); + List getTaskByStageIdList(List stageIdList); + TemplateTasksResp getRespById(String taskId); + public Boolean updateTask(TemplateTaskUpdateReq req); +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateManagerServiceImpl.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateManagerServiceImpl.java index f063151f..c2601de8 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateManagerServiceImpl.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateManagerServiceImpl.java @@ -1,6 +1,7 @@ package cd.casic.ci.process.process.service.template.impl; +import cd.casic.ci.process.dto.req.template.TemplateCreateReq; import cd.casic.ci.process.dto.req.template.TemplateQueryReq; import cd.casic.ci.process.dto.resp.template.TemplateFindResp; import cd.casic.ci.process.dto.resp.template.TemplateStageResp; @@ -59,304 +60,11 @@ public class TemplateManagerServiceImpl extends ServiceImpl stageReqList = templateService.findStageById(pipelineReq.getTemplateId()); -//// stageReqList.forEach(o->{ -//// o.setPipelineId(pipeline.getId()); -//// }); -// //新增初始阶段,无串行并行任务 -// PipStage stageReq1 = new PipStage(); -// stageReq1.setPipelineId(pipeline.getId()); -// stageReq1.setStageName("阶段-1"); -// stageReq1.setCreateTime(LocalDateTime.now()); -// stageReq1.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// stageReq1.setStageSort(1); -// stageReq1.setParentId("-1"); -// stageReq1.setCode(true); -// stageService.save(stageReq1); -// -// PipStage childStage1 = new PipStage(); -// childStage1.setPipelineId(pipeline.getId()); -// childStage1.setStageName("源码"); -// childStage1.setCreateTime(LocalDateTime.now()); -// childStage1.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// childStage1.setStageSort(1); -// childStage1.setCode(false); -// childStage1.setParentId(stageReq1.getId()); -// stageService.save(childStage1); -// -// PipTask childTask11 = new PipTask(); -// childTask11.setCreateTime(LocalDateTime.now()); -// childTask11.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// childTask11.setTaskName("串行任务-1-1"); -// childTask11.setPipelineId(pipeline.getId()); -// childTask11.setTaskType("CODE"); -// childTask11.setTaskSort(1); -// childTask11.setStageId(childStage1.getId()); -// taskService.save(childTask11); -// -// //新增第二个阶段,包含串行和并行任务 -// PipStage stageReq2 = new PipStage(); -// stageReq2.setPipelineId(pipeline.getId()); -// stageReq2.setStageName("阶段-2"); -// stageReq2.setCreateTime(LocalDateTime.now()); -// stageReq2.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// stageReq2.setStageSort(2); -// stageReq2.setParentId("-1"); -// stageReq2.setCode(true); -// stageService.save(stageReq2); -// -// //新增并行阶段 -// PipStage childStage21 = new PipStage(); -// childStage21.setStageName("并行阶段-2-1"); -// childStage21.setPipelineId(pipeline.getId()); -// childStage21.setCreateTime(LocalDateTime.now()); -// childStage21.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// childStage21.setStageSort(1); -// childStage21.setCode(false); -// childStage21.setParentId(stageReq2.getId()); -// stageService.save(childStage21); -// -// //新增串行阶段 -// PipTask childTask21 = new PipTask(); -// childTask21.setPipelineId(pipeline.getId()); -// childTask21.setTaskName("串行任务-2-1"); -// childTask21.setCreateTime(LocalDateTime.now()); -// childTask21.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// childTask21.setTaskType("TEST_CASE_GENERATION"); -// childTask21.setTaskSort(1); -// childTask21.setStageId(childStage21.getId()); -// taskService.save(childTask21); -// -// //------------------------------------------------------------------ -//// PipStage childStage22 = new PipStage(); -//// childStage22.setStageName("并行阶段-2-2"); -//// childStage22.setPipelineId(pipeline.getId()); -//// childStage22.setCreateTime(LocalDateTime.now()); -//// childStage22.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -//// childStage22.setStageSort(2); -//// childStage22.setCode(false); -//// childStage22.setParentId(stageReq2.getId()); -//// stageService.save(childStage22); -//// -//// PipTask childTask22 = new PipTask(); -//// childTask22.setCreateTime(LocalDateTime.now()); -//// childTask22.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -//// childTask22.setTaskName("串行任务-2-2"); -//// childTask22.setPipelineId(pipeline.getId()); -//// childTask22.setTaskType("test"); -//// childTask22.setTaskSort(2); -//// childTask22.setStageId(childStage22.getId()); -//// taskService.save(childTask22); -// -// //创建第三个阶段 -// PipStage stageReq3 = new PipStage(); -// stageReq3.setPipelineId(pipeline.getId()); -// stageReq3.setStageName("阶段-3"); -// stageReq3.setCreateTime(LocalDateTime.now()); -// stageReq3.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// stageReq3.setStageSort(3); -// stageReq3.setParentId("-1"); -// stageReq3.setCode(true); -// stageService.save(stageReq3); -// -// PipStage childStage31 = new PipStage(); -// childStage31.setStageName("并行任务-3-1"); -// childStage31.setPipelineId(pipeline.getId()); -// childStage31.setCreateTime(LocalDateTime.now()); -// childStage31.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// childStage31.setStageSort(1); -// childStage31.setCode(false); -// childStage31.setParentId(stageReq3.getId()); -// stageService.save(childStage31); -// -// PipTask childTask31 = new PipTask(); -// childTask31.setCreateTime(LocalDateTime.now()); -// childTask31.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// childTask31.setTaskName("串行任务-3-1"); -// childTask31.setPipelineId(pipeline.getId()); -// childTask31.setTaskType("AFL"); -// childTask31.setTaskSort(1); -// childTask31.setStageId(childStage31.getId()); -// taskService.save(childTask31); -// -// //创建第四个阶段 -// //TODO -//// PipStage stageReq4 = new PipStage(); -//// stageReq4.setPipelineId(pipeline.getId()); -//// stageReq4.setStageName("阶段-4"); -//// stageReq4.setCreateTime(LocalDateTime.now()); -//// stageReq4.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -//// stageReq4.setStageSort(4); -//// stageReq4.setParentId("-1"); -//// stageReq4.setCode(true); -//// stageService.save(stageReq4); -//// -//// PipStage childStage41 = new PipStage(); -//// childStage41.setStageName("并行任务-4-1"); -//// childStage41.setPipelineId(pipeline.getId()); -//// childStage41.setCreateTime(LocalDateTime.now()); -//// childStage41.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -//// childStage41.setStageSort(1); -//// childStage41.setCode(false); -//// childStage41.setParentId(stageReq4.getId()); -//// stageService.save(childStage41); -//// -//// PipTask childTask41 = new PipTask(); -//// childTask41.setCreateTime(LocalDateTime.now()); -//// childTask41.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId())); -//// childTask41.setTaskName("串行任务-4-1"); -//// childTask41.setPipelineId(pipeline.getId()); -//// childTask41.setTaskType("REPORT"); -//// childTask41.setTaskSort(1); -//// childTask41.setStageId(childStage41.getId()); -//// taskService.save(childTask41); -// -// //TODO 创建对应的鉴权关系 -// //TODO 创建对应的消息分发 -// return pipeline.getId(); -// } -// -// @Override -// public List findPipelineList(PipelineQueryReq pipelineQueryReq) { -// QueryWrapper wrapper = new QueryWrapper<>(); -// if (!ObjectUtils.isEmpty(pipelineQueryReq.getId())){ -// wrapper.eq("id",pipelineQueryReq.getId()); -// } -// if (!ObjectUtils.isEmpty(pipelineQueryReq.getIdList())){ -// wrapper.in("id",pipelineQueryReq.getId()); -// } -// if (!ObjectUtils.isEmpty(pipelineQueryReq.getName())){ -// wrapper.like("name",pipelineQueryReq.getName()); -// } -// if (!ObjectUtils.isEmpty(pipelineQueryReq.getCreator())){ -// wrapper.eq("creator",pipelineQueryReq.getCreator()); -// } -// if (!ObjectUtils.isEmpty(pipelineQueryReq.getCollect())){ -// wrapper.eq("collect",pipelineQueryReq.getCollect()); -// } -// if (!ObjectUtils.isEmpty(pipelineQueryReq.getGroupId())){ -// wrapper.eq("group_id",pipelineQueryReq.getGroupId()); -// } -//// Page page = new Page<>(pipelineQueryReq.getPageNo(), pipelineQueryReq.getPageSize()); -//// Page pipPipelinePage = pipelineDao.selectPage(page, wrapper); -// -// List pipPipelines = pipelineDao.selectList(wrapper); -// if (ObjectUtils.isEmpty(pipPipelines)){ -// return new ArrayList<>(0); -// } -// -// List respList = PipelineConverter.INSTANCE.toRespList(pipPipelines); -// -// //对流水线进行流水线信息赋值 -// respList.forEach(this::setStageAndTask); -// //对用户姓名进行赋值 -// respList.forEach(this::setUserName); -// return respList; -// } -// -// -// @Override -// @Transactional(rollbackFor = Exception.class) -// public void deletePipeline(PipelineReq req) { -// if (StringUtils.isEmpty(req.getId())){ -// throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"id不能为空"); -// } -// -// String pipelineId = req.getId(); -// -// if (ObjectUtils.isEmpty(pipelineId)){ -// throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"请求参数不能为空"); -// } -// -// PipPipeline pipeline = pipelineDao.selectById(pipelineId); -// if (ObjectUtils.isEmpty(pipeline)){ -// throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"流水线不存在"); -// } -// pipelineDao.deleteById(pipelineId); -// -// //根据流水线id查询节点和配置信息 -// PipStage pipStage = new PipStage(); -// pipStage.setPipelineId(pipelineId); -// List pipStageList = stageService.getPipStageList(pipStage); -// if (!CollectionUtils.isEmpty(pipStageList)){ -// List list = pipStageList.stream().map(PipStage::getId).toList(); -// pipStageDao.deleteByIds(list); -// } -// -// PipTask pipTask = new PipTask(); -// pipTask.setPipelineId(pipelineId); -// List task = taskService.getTask(pipTask); -// if (!CollectionUtils.isEmpty(task)){ -// List list = task.stream().map(PipTask::getId).toList(); -// pipTaskDao.deleteByIds(list); -// } -// -// //删除resource表数据 -// if (StringUtils.isNotEmpty(pipeline.getResourceId())){ -// PipResource pipResource = pipResourceDao.selectById(pipeline.getResourceId()); -// -// if (!ObjectUtils.isEmpty(pipResource)){ -// pipResourceDao.deleteById(pipeline.getResourceId()); -// } -// } -// } -// -// @Override -// public void updatePipeline(PipelineUpdateReq pipeline) { -// PipPipeline pipPipeline = new PipPipeline(); -// BeanUtils.copyProperties(pipeline,pipPipeline); -// pipPipeline.setUpdateTime(LocalDateTime.now()); -// pipPipeline.setUpdater(String.valueOf(WebFrameworkUtils.getLoginUserId())); -// pipelineDao.updateById(pipPipeline); -// } -// -// @Override -// public PipelineFindResp findPipelineById(PipelineQueryReq pipelineQueryReq) { -// if (StringUtils.isEmpty(pipelineQueryReq.getId())){ -// throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"id参数不能为空"); -// } -// PipPipeline pipeline = pipelineDao.selectById(pipelineQueryReq.getId()); -// if (ObjectUtils.isEmpty(pipeline)){ -// throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"数据错误,请联系管理员"); -// } -// PipelineFindResp resp = PipelineConverter.INSTANCE.toResp(pipeline); -// setStageAndTask(resp); -// -// return resp; -// } - + public String createTemplateManager(TemplateCreateReq req){ + TemplateManager templateManager = templateConverter.managerCreateReqToManager(req); + save(templateManager); + return templateManager.getId(); + } @Override public PageResult findTemplatePage(TemplateQueryReq query) { diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateStageServiceImpl.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateStageServiceImpl.java new file mode 100644 index 00000000..d901b66d --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateStageServiceImpl.java @@ -0,0 +1,368 @@ +package cd.casic.ci.process.process.service.template.impl; + +import cd.casic.ci.process.dto.req.stage.StageUpdateReq; +import cd.casic.ci.process.dto.req.template.TemplateStageCreateReq; +import cd.casic.ci.process.dto.req.template.TemplateStageUpdateReq; +import cd.casic.ci.process.dto.req.template.TemplateTaskCreateReq; +import cd.casic.ci.process.dto.resp.template.TemplateStageResp; + +import cd.casic.ci.process.process.converter.TemplateStageConverter; +import cd.casic.ci.process.process.dao.template.TemplateStageDao; +import cd.casic.ci.process.process.dataObject.template.TemplateStage; +import cd.casic.ci.process.process.dataObject.template.TemplateTask; +import cd.casic.ci.process.process.service.template.TemplateStageService; +import cd.casic.ci.process.process.service.template.TemplateTaskService; +import cd.casic.ci.process.util.WebFrameworkUtils; +import cd.casic.framework.commons.exception.ServiceException; +import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; +@Service +public class TemplateStageServiceImpl extends ServiceImpl implements TemplateStageService { + @Resource + private TemplateStageDao stageDao; + @Resource + private TemplateTaskService templateTaskService; + @Resource + private TemplateStageConverter stageConverter; + @Transactional(rollbackFor = Exception.class) + @Override + public String createStagesOrTask(TemplateStageCreateReq stageReq) { + String firstStageId = stageReq.getStageId(); + Integer stageSort = stageReq.getStageSort(); + TemplateTaskCreateReq task = stageReq.getTask(); + String taskName = task.getTaskName(); + String secondStageId = task.getStageId(); + Map taskProperties = task.getTaskProperties(); + String taskType = task.getTaskType(); + Integer taskSort = task.getTaskSort(); + String templateId = task.getTemplateId(); + Long loginUserId = WebFrameworkUtils.getLoginUserId(); + TemplateStage firstStage = null; + // 判断是否需要新建阶段,如果没有传第一级tageId而传了sort就是需要创建阶段 + if (StringUtils.isEmpty(firstStageId)) { + // 新建stage + firstStage = new TemplateStage(); + firstStage.setStageName("阶段-"+stageSort); + if (stageSort == null) { + throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"参数有误"); + } + firstStage.setStageSort(stageSort); + firstStage.setCreateTime(LocalDateTime.now()); + firstStage.setParentId("-1"); + firstStage.setTemplateId(templateId); + + firstStage.setCreator(String.valueOf(loginUserId)); + firstStage.setUpdater(String.valueOf(loginUserId)); + firstStage.setUpdateTime(LocalDateTime.now()); + TemplateStage stageQuery = new TemplateStage(); + stageQuery.setTemplateId(templateId); + stageQuery.setParentId("-1"); + List otherStageList = getTemplateStageList(stageQuery); + if (!CollectionUtils.isEmpty(otherStageList)) { + for (TemplateStage stage : otherStageList) { + if (stageSort<=stage.getStageSort()) { + stage.setStageSort(stage.getStageSort()+1); + } + } + updateBatchById(otherStageList); + } + save(firstStage); + } else { + TemplateStage stageQuery = new TemplateStage(); + stageQuery.setId(firstStageId); + stageQuery.setParentId("-1"); + List pipStageList = getTemplateStageList(stageQuery); + if (!CollectionUtils.isEmpty(pipStageList)) { + firstStage = pipStageList.get(0); + } else { + throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"阶段不存在"); + } + } + if (firstStage == null) { + throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"创建节点失败"); + } + TemplateStage secondStage = null; + if (secondStageId==null||taskSort==null) { + // 添加并行节点 + secondStage = new TemplateStage(); + TemplateStage stageQuery = new TemplateStage(); + stageQuery.setParentId(firstStage.getId()); + stageQuery.setTemplateId(templateId); + List pipStageList = getTemplateStageList(stageQuery); + if (CollectionUtils.isEmpty(pipStageList)) { + secondStage.setStageSort(1); + } else { + secondStage.setStageSort(pipStageList.size()+1); + } + secondStage.setCreateTime(LocalDateTime.now()); + secondStage.setUpdateTime(LocalDateTime.now()); + secondStage.setCreator(String.valueOf(loginUserId)); + secondStage.setParentId(firstStage.getId()); + secondStage.setTemplateId(templateId); + secondStage.setUpdater(String.valueOf(loginUserId)); + save(secondStage); + taskSort=1; + secondStageId = secondStage.getId(); + } else { + secondStage = getById(secondStageId); + } + if (secondStage == null) { + throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"创建节点失败"); + } + List taskValues = templateTaskService.getTaskByStageIdList(Arrays.asList(secondStage.getId())); + if (!CollectionUtils.isEmpty(taskValues)) { + for (TemplateTask taskValue : taskValues) { + if (taskValue.getTaskSort()>=taskSort) { + taskValue.setTaskSort(taskValue.getTaskSort()+1); + } + } + templateTaskService.updateBatchById(taskValues); + } + // 保存task + TemplateTask pipTask = new TemplateTask(); + pipTask.setTaskType(taskType); + pipTask.setTaskSort(taskSort); + pipTask.setStageId(secondStageId); + pipTask.setTaskName(taskName); + pipTask.setCreateTime(LocalDateTime.now()); + pipTask.setTaskProperties(taskProperties); + pipTask.setTemplateId(templateId); + pipTask.setUpdateTime(LocalDateTime.now()); + pipTask.setCreator(String.valueOf(loginUserId)); + pipTask.setUpdater(String.valueOf(loginUserId)); + templateTaskService.save(pipTask); + return pipTask.getId(); + } + + @Override + public List findAllStagesTask(String pipelineId) { + //获取流水线主节点 + List stageMainStage = findAllMainStage(pipelineId); + if (stageMainStage.isEmpty()){ + return Collections.emptyList(); + } + List list = new ArrayList<>(); + for (TemplateStage stage : stageMainStage) { + String stagesId = stage.getId(); + //获取从节点 + List allSecondStage = findSecondStageAndTask(stagesId); + List stageRespList = stageConverter.converter(allSecondStage); + TemplateStageResp stageResp = stageConverter.converter(stage); + stageResp.setStageList(stageRespList); + list.add(stageResp); + } + list.sort(Comparator.comparing(TemplateStageResp::getStageSort)); + return list; + } + + @Override + public List findAllFirstStagesAndChild(String pipelineId) { + //获取流水线主节点 + List stageMainStage = findAllMainStage(pipelineId); + if (stageMainStage.isEmpty()){ + return Collections.emptyList(); + } + for (TemplateStage stage : stageMainStage) { + String stagesId = stage.getId(); + //获取从节点 + List allStageStage = findSecondStageAndTask(stagesId); + stage.setStageList(allStageStage); + } + stageMainStage.sort(Comparator.comparing(TemplateStage::getStageSort)); + return stageMainStage; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStagesAndTask(String taskId) { + TemplateTask taskQuery = new TemplateTask(); + taskQuery.setId(taskId); + List taskList = templateTaskService.getTask(taskQuery); + if (CollectionUtils.isEmpty(taskList)) { + return; + } + TemplateTask task = taskList.get(0); + templateTaskService.removeById(taskId); + // 查询上一级stage下有无其他task 没有则连着stage删除 + String stageId = task.getStageId(); + String pipelineId = task.getTemplateId(); + taskQuery = new TemplateTask(); + taskQuery.setStageId(stageId); + List otherTask = templateTaskService.getTask(taskQuery); + if (CollectionUtils.isEmpty(otherTask)) { + // 删除当前task的父stage,然后判断父stage的父级有无其他子级如果没有就继续删除当前阶段 + TemplateStage stageQuery = new TemplateStage(); + stageQuery.setTemplateId(pipelineId); + stageQuery.setId(stageId); + List currStageList = getTemplateStageList(stageQuery); + if (CollectionUtils.isEmpty(currStageList)) { + throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"stage不存在"); + } + TemplateStage currStage = currStageList.get(0); + deleteStages(stageId); + String parentId = currStage.getParentId(); + stageQuery = new TemplateStage(); + stageQuery.setParentId(parentId); + // 查询同阶段其他二级stage,如果不存在其他stage则删除阶段stage并整理sort值 + List otherStageList = getTemplateStageList(stageQuery); + if (CollectionUtils.isEmpty(otherStageList)) { + //没有其他并行路径就需要删除当前阶段 + deleteStages(parentId); + } else { + for (TemplateStage stage : otherStageList) { + if (currStage.getStageSort() getTemplateStageList(TemplateStage pipStage){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(StringUtils.isNotEmpty(pipStage.getId()),TemplateStage::getId,pipStage.getId()); + wrapper.eq(StringUtils.isNotEmpty(pipStage.getTemplateId()),TemplateStage::getTemplateId,pipStage.getTemplateId()); + wrapper.eq(StringUtils.isNotEmpty(pipStage.getParentId()),TemplateStage::getParentId,pipStage.getParentId()); + return stageDao.selectList(wrapper); + } + + + public List findAllMainStage(String pipelineId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(TemplateStage::getTemplateId,pipelineId); + wrapper.eq(TemplateStage::getParentId,"-1"); + return stageDao.selectList(wrapper); + } + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStagesTask(TemplateStageUpdateReq stage) { + String id = stage.getId(); + String stageName = stage.getStageName(); + Integer currStageSort = stage.getStageSort(); + Long loginUserId = WebFrameworkUtils.getLoginUserId(); + TemplateStage updateStage = getById(id); + if (updateStage==null) { + return; + } + + updateStage.setUpdater(String.valueOf(loginUserId)); + updateStage.setUpdateTime(LocalDateTime.now()); + if (currStageSort == null) { + updateStage.setStageName(stageName); + updateById(updateStage); + } else{ + Integer oldStageSort = updateStage.getStageSort(); + if (oldStageSort.equals(currStageSort)) { + return; + } + TemplateStage query = new TemplateStage(); + query.setTemplateId(updateStage.getTemplateId()); + query.setParentId("-1"); + List stageList = getTemplateStageList(query); + if (oldStageSortoldStageSort&&pipStage.getStageSort()<=currStageSort) { + pipStage.setStageSort(pipStage.getStageSort()-1); + } + } else{ + pipStage.setStageSort(currStageSort); + } + } + } else { + // 往左移动 + for (TemplateStage pipStage : stageList) { + if (!pipStage.getId().equals(updateStage.getId())) { + if (pipStage.getStageSort()=currStageSort) { + pipStage.setStageSort(pipStage.getStageSort()+1); + } + } else { + pipStage.setStageSort(currStageSort); + } + } + } + updateBatchById(stageList); + } + + } + public void deleteStages(String stageId) { + stageDao.deleteById(stageId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteFirstStage(String stageId) { + List secondStageAndTask = findSecondStageAndTask(stageId); + for (TemplateStage stage : secondStageAndTask) { + List taskValues = stage.getTaskValues(); + if (!CollectionUtils.isEmpty(taskValues)) { + List taskIdList = taskValues.stream().map(TemplateTask::getId).toList(); + templateTaskService.removeBatchByIds(taskIdList); + } + } + List secondStageIdList = secondStageAndTask.stream().map(TemplateStage::getId).toList(); + removeBatchByIds(secondStageIdList); + TemplateStage byId = getById(stageId); + List allMainStage = findAllMainStage(byId.getTemplateId()); + List updateList = new ArrayList<>(allMainStage.size()); + for (TemplateStage stage : allMainStage) { + if (byId.getStageSort() findSecondStageAndTask(String stagesId){ + List otherStage = findSecondStage(stagesId); + List list = new ArrayList<>(); + List stageIdList = otherStage.stream().map(TemplateStage::getId).toList(); + if (stageIdList.isEmpty()) { + throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"当前阶段下不存在节点"); + } + Map> stageIdTaskMap = templateTaskService.getTaskByStageIdList(stageIdList).stream().collect(Collectors.groupingBy(TemplateTask::getStageId)); + for (TemplateStage stage : otherStage) { + //获取阶段配置及任务 + String otherId = stage.getId(); + List allStageTask = stageIdTaskMap.get(otherId); + allStageTask.sort(Comparator.comparing(TemplateTask::getTaskSort)); + stage.setTaskValues(allStageTask); + list.add(stage); + } + return list; + } + // 获取主stage(阶段)下的子stage + public List findSecondStage(String stageId){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(TemplateStage::getParentId,stageId); + return stageDao.selectList(wrapper); + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateTaskServiceImpl.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateTaskServiceImpl.java new file mode 100644 index 00000000..43b20c69 --- /dev/null +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/template/impl/TemplateTaskServiceImpl.java @@ -0,0 +1,76 @@ +package cd.casic.ci.process.process.service.template.impl; + +import cd.casic.ci.process.dto.req.task.TaskUpdateReq; +import cd.casic.ci.process.dto.req.template.TemplateTaskUpdateReq; +import cd.casic.ci.process.dto.resp.task.TasksResp; +import cd.casic.ci.process.dto.resp.template.TemplateTasksResp; +import cd.casic.ci.process.process.converter.TemplateTaskConverter; +import cd.casic.ci.process.process.dao.template.TemplateTaskDao; +import cd.casic.ci.process.process.dataObject.task.PipTask; +import cd.casic.ci.process.process.dataObject.template.TemplateTask; +import cd.casic.ci.process.process.service.template.TemplateTaskService; +import cd.casic.ci.process.util.WebFrameworkUtils; +import cd.casic.framework.commons.exception.ServiceException; +import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +@Service +public class TemplateTaskServiceImpl extends ServiceImpl implements TemplateTaskService { + @Resource + private TemplateTaskDao taskDao; + @Resource + private TemplateTaskConverter taskConverter; + @Override + public List getTask(TemplateTask task) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(StringUtils.isNotEmpty(task.getId()),TemplateTask::getId,task.getId()); + wrapper.eq(StringUtils.isNotEmpty(task.getTemplateId()),TemplateTask::getTemplateId,task.getTemplateId()); + wrapper.eq(StringUtils.isNotEmpty(task.getStageId()),TemplateTask::getStageId,task.getStageId()); + return taskDao.selectList(wrapper); + } + @Override + public List getTaskByStageIdList(List stageIdList){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(TemplateTask::getStageId,stageIdList); + return taskDao.selectList(wrapper); + } + @Override + public TemplateTasksResp getRespById(String taskId){ + TemplateTask pipTask = new TemplateTask(); + pipTask.setId(taskId); + List taskList = getTask(pipTask); + if (CollectionUtils.isEmpty(taskList)) { + return null; + } + return taskConverter.doToResp(taskList.get(0)); + } + + @Override + public Boolean updateTask(TemplateTaskUpdateReq req) { + if (StringUtils.isEmpty(req.getId())) { + throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"传入id有问题"); + } + TemplateTask byId = getById(req.getId()); + if (byId == null) { + throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"task不存在"); + } + String taskName = req.getTaskName(); + Map taskProperties = req.getTaskProperties(); + String taskType = req.getTaskType(); + byId.setTaskProperties(taskProperties); + byId.setTaskType(taskType); + byId.setTaskName(taskName); + byId.setUpdater(WebFrameworkUtils.getLoginUserIdStr()); + byId.setUpdateTime(LocalDateTime.now()); + return updateById(byId); + } +} diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/testCase/TestCaseManagerService.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/testCase/TestCaseManagerService.java index 936cff83..cb9bdaad 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/testCase/TestCaseManagerService.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/testCase/TestCaseManagerService.java @@ -3,12 +3,17 @@ package cd.casic.ci.process.process.service.testCase; import cd.casic.ci.process.dto.req.testCase.TestCaseManagerQueryReq; import cd.casic.ci.process.dto.req.testCase.TestCaseManagerReq; +import cd.casic.ci.process.dto.resp.testCase.TestCaseManagerDownloadResp; import cd.casic.ci.process.dto.resp.testCase.TestCaseManagerResp; import cd.casic.ci.process.process.dataObject.testCase.TestCaseManager; import cd.casic.framework.commons.pojo.PageResult; import com.baomidou.mybatisplus.extension.service.IService; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.SftpException; +import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; +import java.io.IOException; import java.util.List; /** @@ -32,4 +37,6 @@ public interface TestCaseManagerService extends IService { TestCaseManagerResp findById(String id); + TestCaseManagerDownloadResp downLoadById(String id ); + } diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/testCase/impl/TestCaseManagerServiceImpl.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/testCase/impl/TestCaseManagerServiceImpl.java index 32c94c9e..c193169b 100644 --- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/testCase/impl/TestCaseManagerServiceImpl.java +++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/testCase/impl/TestCaseManagerServiceImpl.java @@ -4,6 +4,7 @@ package cd.casic.ci.process.process.service.testCase.impl; import cd.casic.ci.process.dto.req.testCase.TestCaseManagerQueryReq; import cd.casic.ci.process.dto.req.testCase.TestCaseManagerReq; import cd.casic.ci.process.dto.resp.testCase.TestCaseInfoResp; +import cd.casic.ci.process.dto.resp.testCase.TestCaseManagerDownloadResp; import cd.casic.ci.process.dto.resp.testCase.TestCaseManagerResp; import cd.casic.ci.process.process.converter.TestCaseManagerConverter; import cd.casic.ci.process.process.dao.testCase.TestCaseInfoDao; @@ -23,21 +24,22 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.jcraft.jsch.ChannelExec; -import com.jcraft.jsch.JSch; -import com.jcraft.jsch.JSchException; -import com.jcraft.jsch.Session; +import com.jcraft.jsch.*; import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.*; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; /** * @author HopeLi @@ -64,7 +66,8 @@ public class TestCaseManagerServiceImpl extends ServiceImpl byManagerIds = testCaseInfoService.findByManagerIds(Collections.singletonList(id)); + + for (TestCaseInfoResp byManagerId : byManagerIds) { + InputStream inputStream = sftp.get(byManagerId.getTestFilePath()); + String fileName = byManagerId.getFileName(); + ZipEntry zipEntry = new ZipEntry(fileName); + zipOutputStream.putNextEntry(zipEntry); + IOUtils.copy(inputStream,zipOutputStream); + zipOutputStream.closeEntry(); + inputStream.close(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + byte[] byteArray = bos.toByteArray(); + String file = Base64.getEncoder().encodeToString(byteArray); + TestCaseManagerDownloadResp testCaseManagerDownloadResp = new TestCaseManagerDownloadResp(); + testCaseManagerDownloadResp.setFile(file); + testCaseManagerDownloadResp.setFileName("SEED.zip"); + return testCaseManagerDownloadResp; + } + private void setUserName(TestCaseManagerResp testCaseManagerResp) { if (!StringUtils.isEmpty(testCaseManagerResp.getCreator())){ @@ -219,13 +260,15 @@ public class TestCaseManagerServiceImpl extends ServiceImplmodule-ci-execute module-ci-process-api module-ci-process-biz + module-ci-machine modules diff --git a/ops-server/src/test/java/cd/casic/server/ClocTest.java b/ops-server/src/test/java/cd/casic/server/ClocTest.java new file mode 100644 index 00000000..895b3d9d --- /dev/null +++ b/ops-server/src/test/java/cd/casic/server/ClocTest.java @@ -0,0 +1,41 @@ +package cd.casic.server; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +@SpringBootTest(classes = {OpsServerApplication.class}) +@ActiveProfiles("local") +public class ClocTest { + public void fileExit(){ + File file = new File("/ops-pro/ops-server/src/test/resources/java.zip"); + } + + @Test + public void test01() throws IOException, InterruptedException { + // 构建命令 + ProcessBuilder pb = new ProcessBuilder("D:/cloc/cloc.exe", "/ops-pro/ops-server/src/test/resources/java.zip", "--json"); + pb.redirectErrorStream(true); // 合并标准输出和错误输出 + + // 启动进程 + Process process = pb.start(); + StringBuilder stringBuilder = new StringBuilder(); + + + // 读取输出 + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + } + System.out.println(stringBuilder.toString()); + // 等待进程结束并获取返回值 + int exitCode = process.waitFor(); + System.out.println("命令执行结束,返回值:" + exitCode); + } +} diff --git a/ops-server/src/test/java/cd/casic/server/SftpTest.java b/ops-server/src/test/java/cd/casic/server/SftpTest.java index c74c4b5c..26c10c68 100644 --- a/ops-server/src/test/java/cd/casic/server/SftpTest.java +++ b/ops-server/src/test/java/cd/casic/server/SftpTest.java @@ -11,6 +11,8 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import java.io.File; +import java.io.InputStream; +import java.util.Properties; import java.util.Vector; @SpringBootTest(classes = {OpsServerApplication.class}) diff --git a/ops-server/src/test/java/cd/casic/server/ZipFileTest.java b/ops-server/src/test/java/cd/casic/server/ZipFileTest.java new file mode 100644 index 00000000..9c43c154 --- /dev/null +++ b/ops-server/src/test/java/cd/casic/server/ZipFileTest.java @@ -0,0 +1,69 @@ +package cd.casic.server; + +import cd.casic.ci.process.process.dataObject.machine.MachineInfo; +import cd.casic.ci.process.properties.TargetFileUploadProperties; +import cd.casic.ci.process.util.CryptogramUtil; +import cd.casic.ci.process.util.SftpUploadUtil; +import com.jcraft.jsch.*; +import jakarta.annotation.Resource; +import jodd.io.IOUtil; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import java.io.*; +import java.util.Properties; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +@SpringBootTest(classes = {OpsServerApplication.class}) +@ActiveProfiles("local") +public class ZipFileTest { + @Resource + TargetFileUploadProperties properties; + String[] testFilePath = new String[]{ + "/home/ops/ops-pro/file/af4b1435-8fb0-453d-acef-eaec75c67dd8/QQ图片20250623102626.png", + "/home/ops/ops-pro/file/7ffb5bb7-9ea2-4d8b-9e0e-b6c3f99107b5/新建 文本文档.txt", + "/home/ops/ops-pro/file/2622340c-20db-48fc-bca2-d867da3149aa/.nodemid", + "/home/ops/ops-pro/file/f601e6d7-050f-4c92-a353-e1db64e048e1/1 (2).txt", + "/home/ops/ops-pro/file/9bf7c208-0576-4408-833e-e0d7eecc5a8a/office账户.txt", + "/home/ops/ops-pro/file/332143a2-52da-4e29-8a3d-78071d4e3559/office账户.txt", + "/home/ops/ops-pro/file/bbf03a24-5a48-4863-b1b9-c52bb00a8b0f/office账户.txt", + "/home/ops/ops-pro/file/6ae5f778-e12c-48f2-bce1-8748e2435e26/脚本.txt", + "/home/ops/ops-pro/file/47c98d3b-553a-4934-b4c4-f9b185eac04a/1.txt", + "/home/ops/ops-pro/file/cafb8135-f1d1-42db-bb02-1444cda937fd/ximenzi.txt", + "/home/ops/ops-pro/file/0e78423d-b4b6-4442-b225-e66309515d42/office账户.txt", + "/home/ops/ops-pro/file/40831b9c-eb35-4eb9-973a-f087b48105e6/office账户.txt" + }; + @Test + public void testZip() throws JSchException, SftpException { + JSch jsch = new JSch(); + Session session = jsch.getSession(properties.getUsername(), properties.getRemoteHost(), properties.getRemotePort()); + session.setPassword(properties.getPassword()); + + // 跳过 host key 检查 + Properties config = new Properties(); + config.put("StrictHostKeyChecking", "no"); + session.setConfig(config); + + session.connect(); + ChannelSftp sftp = (ChannelSftp) session.openChannel("sftp"); + sftp.connect(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + for (String path : testFilePath) { + InputStream inputStream = sftp.get(path); + String fileName = path.substring(path.lastIndexOf("/")); + try (ZipOutputStream zipOutputStream = new ZipOutputStream(bos)){ + ZipEntry zipEntry = new ZipEntry(fileName); + zipOutputStream.putNextEntry(zipEntry); + IOUtils.copy(inputStream,zipOutputStream); + zipOutputStream.closeEntry(); + inputStream.close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + System.out.println(bos.size()); + } +}