Compare commits
27 Commits
master
...
jenkins-en
Author | SHA1 | Date | |
---|---|---|---|
![]() |
97ffb19c03 | ||
![]() |
2d4653b29a | ||
![]() |
66bc6a1250 | ||
![]() |
926c1af1e1 | ||
![]() |
f28fe4ecdf | ||
![]() |
56150c156b | ||
![]() |
891a332c59 | ||
![]() |
7cd4396001 | ||
![]() |
62b0caa3da | ||
![]() |
4815b590c4 | ||
![]() |
a238538106 | ||
![]() |
ea35ed1f0b | ||
![]() |
c26a183209 | ||
![]() |
4b8dfe978a | ||
![]() |
30c201a230 | ||
![]() |
818c2e0198 | ||
![]() |
a7398d265c | ||
![]() |
04afb442cf | ||
![]() |
b65bdd95bc | ||
![]() |
790193d0c9 | ||
![]() |
1028cc0705 | ||
![]() |
a7738d2add | ||
![]() |
1d8a1f6eb9 | ||
![]() |
db95a112bc | ||
![]() |
5410bd4374 | ||
![]() |
6642fc493b | ||
![]() |
6e317f9b8c |
3
.idea/compiler.xml
generated
3
.idea/compiler.xml
generated
@ -7,6 +7,7 @@
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="machine-management-module" />
|
||||
</profile>
|
||||
<profile name="Annotation profile for ops-pro" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
@ -53,6 +54,7 @@
|
||||
<module name="module-ci-dispatch-api" target="17" />
|
||||
<module name="module-ci-environment" target="17" />
|
||||
<module name="module-ci-event" target="17" />
|
||||
<module name="module-ci-execute" target="1.5" />
|
||||
<module name="module-ci-log" target="17" />
|
||||
<module name="module-ci-market" target="17" />
|
||||
<module name="module-ci-project" target="17" />
|
||||
@ -69,6 +71,7 @@
|
||||
<module name="app-plugins" options="-parameters" />
|
||||
<module name="commons" options="-parameters" />
|
||||
<module name="framework" options="-parameters" />
|
||||
<module name="machine-management-module" options="-parameters" />
|
||||
<module name="module-ci-commons" options="-parameters" />
|
||||
<module name="module-ci-engine" options="-parameters" />
|
||||
<module name="module-ci-plugin" options="-parameters" />
|
||||
|
1
.idea/encodings.xml
generated
1
.idea/encodings.xml
generated
@ -39,6 +39,7 @@
|
||||
<file url="file://$PROJECT_DIR$/framework/spring-boot-starter-websocket/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/framework/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/framework/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/modules/ee/machine-management-module/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/modules/module-ci-common-pipeline/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/modules/module-ci-common-pipeline/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/modules/module-ci-common/src/main/java" charset="UTF-8" />
|
||||
|
10
.idea/jarRepositories.xml
generated
10
.idea/jarRepositories.xml
generated
@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="huaweicloud" />
|
||||
<option name="name" value="huawei" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/public" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="huaweicloud" />
|
||||
<option name="name" value="huawei" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/public" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="aliyunmaven" />
|
||||
<option name="name" value="aliyun" />
|
||||
|
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
@ -52,6 +52,7 @@
|
||||
<option value="$PROJECT_DIR$/modules/module-ci-store-api/pom.xml" />
|
||||
<option value="$PROJECT_DIR$/modules/module-ci-process-biz/pom.xml" />
|
||||
<option value="$PROJECT_DIR$/modules/module-ci-process-api/pom.xml" />
|
||||
<option value="$PROJECT_DIR$/modules/ee/machine-management-module/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="ignoredFiles">
|
||||
|
69
modules/module-ci-machine/pom.xml
Normal file
69
modules/module-ci-machine/pom.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cd.casic.boot</groupId>
|
||||
<artifactId>modules</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>module-ci-machine</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
<version>${revision}</version>
|
||||
<name>${project.artifactId}</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>cd.casic.boot</groupId>
|
||||
<artifactId>commons</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>3.15.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 机器连接-->
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
<version>0.1.55</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.32</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<version>3.5.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- SpringDoc OpenAPI 依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.3.0</version>
|
||||
</dependency>
|
||||
<!--文件上传-->
|
||||
<dependency>
|
||||
<groupId>cd.casic.boot</groupId>
|
||||
<artifactId>module-infra-biz</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,33 @@
|
||||
package cd.casic.module.machine.configuration;
|
||||
|
||||
import cd.casic.module.infra.framework.file.core.client.s3.S3FileClientConfig;
|
||||
import cd.casic.module.machine.utils.AliYunOssClient;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class AliYunOssConfig extends S3FileClientConfig{
|
||||
@Value("${aliyun.oss.endpoint}")
|
||||
private String endpoint;
|
||||
@Value("${aliyun.oss.accessKeyId}")
|
||||
private String accessKey;
|
||||
@Value("${aliyun.oss.accessKeySecret}")
|
||||
private String accessSecret;
|
||||
@Value("${aliyun.oss.bucketName}")
|
||||
private String bucket;
|
||||
// 定义 S3 客户端 Bean
|
||||
@Bean
|
||||
public AliYunOssClient aliYunClient() {
|
||||
// 创建配置对象
|
||||
S3FileClientConfig config = new AliYunOssConfig();
|
||||
config.setEndpoint(endpoint);
|
||||
config.setAccessKey(accessKey);
|
||||
config.setAccessSecret(accessSecret);
|
||||
config.setBucket(bucket);
|
||||
AliYunOssClient aliYunOssClient = new AliYunOssClient(1L, config);
|
||||
// 创建并返回客户端实例
|
||||
aliYunOssClient.init();
|
||||
return aliYunOssClient;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
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 UPLOADING_FILE_FAIL = new ErrorCode(1_003_000_001, "上传文件失败");
|
||||
ErrorCode DOWNLOAD_FILE_FAIL = new ErrorCode(1_003_000_002, "下载失败");
|
||||
ErrorCode FILENAME_NULL = new ErrorCode(1_003_000_003, "文件名为空");
|
||||
ErrorCode READ_FILE_FAIL = new ErrorCode(1_003_000_004, "读取文件失败");
|
||||
ErrorCode DELETE_FILE_FAIL = new ErrorCode(1_003_000_005, "删除文件失败");
|
||||
|
||||
ErrorCode PARAMETER_ERROR = new ErrorCode(1_003_000_008, "参数错误");
|
||||
// ========== 机器环境变量模块 1-003-000-009 ==========
|
||||
ErrorCode MACHINE_ENV_NULL = new ErrorCode(1_003_000_009, "机器环境变量为空");
|
||||
ErrorCode MACHINE_ENV_NOT_EXISTS = new ErrorCode(1_003_000_009, "机器不存在");
|
||||
ErrorCode MACHINE_ENV_KEY_ILLEGAL = new ErrorCode(1_003_000_010, "机器环境变量键不合法");
|
||||
// ========== 机器代理模块 1-003-000-006 ==========
|
||||
ErrorCode MACHINE_PROXY_HOST_IP_NULL = new ErrorCode(1_003_000_006, "机器代理主机地址为空");
|
||||
ErrorCode MACHINE_PROXY_USER_NAME_NULL = new ErrorCode(1_003_000_006, "机器代理用户名为空");
|
||||
ErrorCode MACHINE_PROXY_NOT_EXISTS = new ErrorCode(1_003_000_007, "机器代理不存在");
|
||||
ErrorCode MACHINE_PROXY_TYPE_NOT_EXISTS = new ErrorCode(1_003_000_007, "机器代理类型不存在");
|
||||
ErrorCode MACHINE_PROXY_IS_ONLINE = new ErrorCode(1_003_000_007, "机器代理在线,不能删除");
|
||||
|
||||
ErrorCode OSS_PARAM_NULL = new ErrorCode(1_003_000_011, "oss参数无法读取");
|
||||
ErrorCode SECRETKEY_NULL = new ErrorCode(1_003_000_012, "密钥为空");
|
||||
}
|
||||
|
||||
|
@ -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.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<Long> 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<Boolean> updateEnv(@Valid@RequestBody MachineEnvVO machineEnvVO) {
|
||||
machineEnvService.updateEnv(machineEnvVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除机器的环境变量")
|
||||
@PreAuthorize("@ss.hasPermission('ci:machineEnv:delete')")
|
||||
public CommonResult<Boolean> deleteEnv(@RequestParam("id") Long id) {
|
||||
machineEnvService.deleteEnv(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/deleteList")
|
||||
@Operation(summary = "批量删除机器环境变量")
|
||||
@PreAuthorize("@ss.hasPermission('ci:machineEnv:delete')")
|
||||
public CommonResult<Boolean> deleteEnvList(@RequestParam("ids") String ids) {
|
||||
machineEnvService.deleteEnvList(ids);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/getEnv")
|
||||
@Operation(summary = "获取机器的环境变量")
|
||||
public CommonResult<MachineEnvVO> getEnv(@RequestParam("id") Long id) {
|
||||
MachineEnvVO machineEnvVO = machineEnvService.getEnv(id);
|
||||
return success(machineEnvVO);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/list")
|
||||
@Operation(summary = "获取环境变量列表")
|
||||
public CommonResult<PageResult<MachineEnvVO>> getEnvPage(@Valid @RequestBody MachineEnvVO machineEnvVO) {
|
||||
PageResult<MachineEnvDO> pageResult = machineEnvService.getEnvPage(machineEnvVO);
|
||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||
return success(new PageResult<>(pageResult.getTotal()));
|
||||
}
|
||||
return success(BeanUtils.toBean(pageResult, MachineEnvVO.class));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,126 @@
|
||||
//package cd.casic.module.machine.controller;
|
||||
//
|
||||
//import cd.casic.framework.commons.pojo.CommonResult;
|
||||
//import cd.casic.framework.commons.pojo.PageResult;
|
||||
//import cd.casic.module.machine.dal.dataobject.MachineInfo;
|
||||
//import cd.casic.module.machine.enums.ConnectionStatus;
|
||||
//import cd.casic.module.machine.service.MachineInfoService;
|
||||
//import cd.casic.module.machine.controller.vo.MachineInfoDto;
|
||||
//import io.swagger.v3.oas.annotations.Operation;
|
||||
//import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
//import jakarta.annotation.Resource;
|
||||
//import org.springframework.web.bind.annotation.*;
|
||||
//
|
||||
//import java.util.Map;
|
||||
//
|
||||
//import static cd.casic.framework.commons.pojo.CommonResult.success;
|
||||
//
|
||||
//@RestController
|
||||
//@Tag(name = "机器信息管理")
|
||||
//@RequestMapping("/api/machineInfo")
|
||||
//public class MachineInfoController {
|
||||
// @Resource
|
||||
// private MachineInfoService machineInfoService;
|
||||
//
|
||||
// @PostMapping("/add")
|
||||
// @Operation(summary = "新增机器信息")
|
||||
// public CommonResult<Boolean> add(@RequestBody MachineInfoDto machineInfoDto) {
|
||||
// return success(machineInfoService.addMachineInfo(machineInfoDto));
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @PostMapping("/list")
|
||||
// @Operation(summary = "获取机器信息列表")
|
||||
// public CommonResult<PageResult<MachineInfoDto>> list(@RequestBody MachineInfoDto machineInfoDto) {
|
||||
// return success(machineInfoService.listMachineInfo(machineInfoDto));
|
||||
// }
|
||||
//
|
||||
// @PutMapping("/update")
|
||||
// @Operation(summary = "编辑机器信息")
|
||||
// public CommonResult<Boolean> update(@RequestBody MachineInfoDto machineInfoDto) {
|
||||
// return success(machineInfoService.updateMachineInfo(machineInfoDto));
|
||||
// }
|
||||
//
|
||||
// @PutMapping("/updateStatus")
|
||||
// @Operation(summary = "机器启用/停用")
|
||||
// public CommonResult<Boolean> updateStatus(@RequestBody MachineInfoDto machineInfoDto) {
|
||||
// return success(machineInfoService.updateStatus(machineInfoDto));
|
||||
// }
|
||||
//
|
||||
// @PutMapping("/bindingSecretKey")
|
||||
// @Operation(summary = "绑定密钥")
|
||||
// public CommonResult<Boolean> bindingSecretKey(@RequestBody MachineInfoDto machineInfoDto) {
|
||||
// return success(machineInfoService.bindingSecretKey(machineInfoDto));
|
||||
// }
|
||||
//
|
||||
// @DeleteMapping("/delete")
|
||||
// @Operation(summary = "机器信息删除")
|
||||
// public CommonResult<Boolean> delete(@RequestParam Long machineInfoId) {
|
||||
// machineInfoService.deleteMachineInfo(machineInfoId);
|
||||
// return success(true);
|
||||
// }
|
||||
//
|
||||
// @DeleteMapping("/deleteList")
|
||||
// @Operation(summary = "批量删除机器信息")
|
||||
// public CommonResult<Boolean> deleteList(@RequestParam String machineInfoIds) {
|
||||
// machineInfoService.deleteList(machineInfoIds);
|
||||
// return success(true);
|
||||
// }
|
||||
//
|
||||
// @PostMapping("/test")
|
||||
// @Operation(summary = "测试机器连接")
|
||||
// public CommonResult<Boolean> testConnection(@RequestParam Long id) {
|
||||
// return success(machineInfoService.testConnection(id));
|
||||
// }
|
||||
//
|
||||
// @GetMapping("/status/{machineName}")
|
||||
// @Operation(summary = "获取机器连接状态")
|
||||
// public CommonResult<ConnectionStatus> getConnectionStatus(@PathVariable String machineName) {
|
||||
// return success(machineInfoService.getConnectionStatus(machineName));
|
||||
// }
|
||||
//
|
||||
// @GetMapping("/status/all")
|
||||
// @Operation(summary = "获取所有机器连接状态")
|
||||
// public CommonResult<Map<String, ConnectionStatus>> getAllConnectionStatus() {
|
||||
// return success(machineInfoService.getAllConnectionStatus());
|
||||
// }
|
||||
//
|
||||
// @PostMapping("/connect")
|
||||
// @Operation(summary = "建立机器连接")
|
||||
// public CommonResult<String> connect(@RequestBody MachineInfo machineInfo) {
|
||||
// return success(machineInfoService.connect(machineInfo));
|
||||
// }
|
||||
//
|
||||
// @PostMapping("/disconnect/{sessionId}")
|
||||
// @Operation(summary = "断开机器连接")
|
||||
// public CommonResult<Boolean> disconnect(@PathVariable String sessionId) {
|
||||
// return success(machineInfoService.disconnect(sessionId));
|
||||
// }
|
||||
//
|
||||
// @PostMapping("/execute/{sessionId}")
|
||||
// @Operation(summary = "执行远程命令")
|
||||
// public CommonResult<String> executeCommand(
|
||||
// @PathVariable String sessionId,
|
||||
// @RequestBody String command) {
|
||||
//
|
||||
// return success(machineInfoService.executeCommand(sessionId, command));
|
||||
// }
|
||||
//
|
||||
// @PostMapping("/upload/{sessionId}")
|
||||
// @Operation(summary = "上传文件到远程机器")
|
||||
// public CommonResult<Boolean> uploadFile(
|
||||
// @PathVariable String sessionId,
|
||||
// @RequestParam String localFilePath,
|
||||
// @RequestParam String remoteFilePath) {
|
||||
// return success(machineInfoService.uploadFile(sessionId, localFilePath, remoteFilePath));
|
||||
// }
|
||||
//
|
||||
// @PostMapping("/download/{sessionId}")
|
||||
// @Operation(summary = "从远程机器下载文件")
|
||||
// public CommonResult<Boolean> downloadFile(
|
||||
// @PathVariable String sessionId,
|
||||
// @RequestParam String remoteFilePath,
|
||||
// @RequestParam String localFilePath) {
|
||||
// return success(machineInfoService.downloadFile(sessionId, remoteFilePath, localFilePath));
|
||||
// }
|
||||
//}
|
@ -0,0 +1,72 @@
|
||||
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<Long> 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<Boolean> updateProxy(@Valid @RequestBody MachineProxyVO machineProxyVO) {
|
||||
machineProxyService.updateProxy(machineProxyVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
@Operation(summary = "获取代理列表")
|
||||
public CommonResult<PageResult<MachineProxyVO>> getProxyPage(@Valid @RequestBody MachineProxyVO machineProxyVO) {
|
||||
PageResult<MachineProxyDO> 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<Map<Integer, Long>> getStatusStatistics() {
|
||||
return success(machineProxyService.getAllProxyStatus());
|
||||
}
|
||||
|
||||
|
||||
@DeleteMapping("/deleteList")
|
||||
@Operation(summary = "批量删除代理")
|
||||
@PreAuthorize("@ss.hasPermission('ci:machineProxy:delete')")
|
||||
public CommonResult<Boolean> deleteProxyList(@RequestParam String ids) {
|
||||
machineProxyService.deleteProxyList(ids);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//package cd.casic.module.machine.controller;
|
||||
//
|
||||
//import cd.casic.framework.commons.pojo.CommonResult;
|
||||
//import cd.casic.framework.commons.pojo.PageResult;
|
||||
//import cd.casic.module.machine.dal.dataobject.SecretKey;
|
||||
//import cd.casic.module.machine.service.SecretKeyService;
|
||||
//import cd.casic.module.machine.controller.vo.SecretKeyDto;
|
||||
//import io.swagger.v3.oas.annotations.Operation;
|
||||
//import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
//import jakarta.annotation.Resource;
|
||||
//import org.springframework.web.bind.annotation.*;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
//import static cd.casic.framework.commons.pojo.CommonResult.success;
|
||||
//
|
||||
//@RestController
|
||||
//@RequestMapping("/api/secretKey")
|
||||
//@Tag(name = "密钥管理")
|
||||
//public class SecretKeyController {
|
||||
// @Resource
|
||||
// private SecretKeyService secretKeyService;
|
||||
//
|
||||
// @PostMapping(value = "/add")
|
||||
// @Operation(summary = "新增密钥")
|
||||
// public CommonResult<Boolean> add(@RequestBody SecretKeyDto secretKeyDto) throws Exception {
|
||||
// return success(secretKeyService.addSecretKey(secretKeyDto));
|
||||
// }
|
||||
//
|
||||
// @PutMapping("/bindingMachine")
|
||||
// @Operation(summary = "绑定机器")
|
||||
// public CommonResult<Boolean> bindingMachine(@RequestParam("secretKeyId") Long secretKeyId, @RequestParam("machineIds") List<Long> machineIds) {
|
||||
// secretKeyService.bindingMachine(secretKeyId, machineIds);
|
||||
// return success(true);
|
||||
// }
|
||||
//
|
||||
// @PutMapping("/update")
|
||||
// @Operation(summary = "编辑密钥信息")
|
||||
// public CommonResult<Boolean> update(@RequestBody SecretKeyDto secretKeyDto) {
|
||||
// return success(secretKeyService.updateSecretKey(secretKeyDto));
|
||||
// }
|
||||
//
|
||||
// @DeleteMapping("/deleteList")
|
||||
// @Operation(summary = "批量删除密钥")
|
||||
// public CommonResult<Boolean> deleteList(@RequestParam("secretKeyId") List<Long> secretKeyIds) {
|
||||
// return success(secretKeyService.deleteList(secretKeyIds));
|
||||
// }
|
||||
//
|
||||
// @PostMapping("/list")
|
||||
// @Operation(summary = "获取密钥信息列表")
|
||||
// public CommonResult<PageResult<SecretKey>> list(@RequestBody SecretKeyDto secretKeyDto) {
|
||||
// return success(secretKeyService.listSecretKey(secretKeyDto));
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
@ -0,0 +1,36 @@
|
||||
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;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package cd.casic.module.machine.controller.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MachineInfoDto extends PageDto {
|
||||
private Long id;
|
||||
|
||||
private Date createDate;
|
||||
|
||||
private Date updateDate;
|
||||
|
||||
private String name;
|
||||
|
||||
private String tag;
|
||||
|
||||
private String hostIp;
|
||||
|
||||
private String description;
|
||||
|
||||
private String username;
|
||||
|
||||
private String status;
|
||||
|
||||
private Integer sshPort;
|
||||
|
||||
private String password;
|
||||
|
||||
private Long secretKeyId;
|
||||
|
||||
private Long machineProxyId;
|
||||
|
||||
private String authenticationType;
|
||||
|
||||
private String machineInfoType;
|
||||
|
||||
private int isProxy;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
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;
|
||||
|
||||
@Schema(description = "版本号", example = "1.0.0")
|
||||
private String version;
|
||||
|
||||
@Schema(description = "状态(ONLINE:在线,OFFLINE:离线)", requiredMode = Schema.RequiredMode.REQUIRED, example = "ONLINE")
|
||||
private String status;
|
||||
|
||||
@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;
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package cd.casic.module.machine.controller.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SecretKeyDto extends PageDto {
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
//存储路径,本地上传文件路径
|
||||
private String path;
|
||||
|
||||
private String fileName;
|
||||
|
||||
//密钥密码
|
||||
private String password;
|
||||
|
||||
private Date createDate;
|
||||
|
||||
private Date updateDate;
|
||||
|
||||
private List<Long> machineInfoIds;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cd.casic.module.machine.convert;
|
||||
|
||||
import cd.casic.module.machine.controller.vo.MachineEnvVO;
|
||||
import cd.casic.module.machine.dal.dataobject.MachineEnvDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@Mapper
|
||||
public interface MachineEnvConvert {
|
||||
|
||||
MachineEnvConvert INSTANCE = Mappers.getMapper(MachineEnvConvert.class);
|
||||
|
||||
// 转换实体为VO
|
||||
default MachineEnvVO convertToVO(MachineEnvDO machineEnvDO) {
|
||||
MachineEnvVO VO = new MachineEnvVO();
|
||||
VO.setId(machineEnvDO.getId());
|
||||
VO.setEnvKey(machineEnvDO.getEnvKey());
|
||||
VO.setEnvValue(machineEnvDO.getEnvValue());
|
||||
VO.setDescription(machineEnvDO.getDescription());
|
||||
VO.setCreateTime(machineEnvDO.getCreateTime());
|
||||
VO.setUpdateTime(machineEnvDO.getUpdateTime());
|
||||
return VO;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package cd.casic.module.machine.dal.dataobject;
|
||||
|
||||
|
||||
import cd.casic.framework.mybatis.core.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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,69 @@
|
||||
package cd.casic.module.machine.dal.dataobject;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import cd.casic.module.machine.enums.AuthenticationType;
|
||||
import cd.casic.module.machine.enums.MachineInfoStatus;
|
||||
import cd.casic.module.machine.enums.MachineInfoType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName(value = "machine_info")
|
||||
public class MachineInfo extends BaseEntity {
|
||||
@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;
|
||||
|
||||
@TableField(exist = false)
|
||||
private MachineInfoType machineInfoType;
|
||||
|
||||
@TableField(value = "machine_info_type_code")
|
||||
private int machineInfoTypeCode;
|
||||
|
||||
|
||||
@TableField(exist = false)
|
||||
private MachineInfoStatus status;
|
||||
|
||||
@TableField(value = "status_code")
|
||||
private int statusCode;
|
||||
|
||||
//用户名
|
||||
@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;
|
||||
|
||||
@TableField(value = "authentication_type_code")
|
||||
private int authenticationTypeCode;
|
||||
|
||||
@TableField(exist = false)
|
||||
private AuthenticationType authenticationType;
|
||||
|
||||
@TableField(value = "is_proxy")
|
||||
private int isProxy;
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package cd.casic.module.machine.dal.dataobject;
|
||||
|
||||
import cd.casic.framework.mybatis.core.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;
|
||||
|
||||
//todo 字典??
|
||||
@TableField(value = "proxy_type")
|
||||
private int proxyType;
|
||||
|
||||
@TableField(value = "version")
|
||||
private String version;
|
||||
|
||||
//todo 字典??
|
||||
@TableField(value = "status")
|
||||
private int status;
|
||||
|
||||
@TableField(value = "username")
|
||||
private String username;
|
||||
|
||||
@TableField(value = "password")
|
||||
private String password;
|
||||
|
||||
@TableField(value = "description")
|
||||
private String description;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package cd.casic.module.machine.dal.dataobject;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
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 SecretKey extends BaseEntity{
|
||||
@TableField(value = "name")
|
||||
private String name;
|
||||
|
||||
@TableField(value = "description")
|
||||
private String description;
|
||||
|
||||
//oss存储路径
|
||||
@TableField(value = "path")
|
||||
private String path;
|
||||
|
||||
@TableField
|
||||
private String fileName;
|
||||
|
||||
//密钥密码
|
||||
@TableField(value = "password")
|
||||
private String password;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
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<MachineEnvDO> {
|
||||
default PageResult<MachineEnvDO>selectPage(MachineEnvVO machineEnvVO){
|
||||
return selectPage(machineEnvVO,new LambdaQueryWrapperX<MachineEnvDO>()
|
||||
.likeIfPresent(MachineEnvDO::getEnvKey, machineEnvVO.getEnvKey())
|
||||
.likeIfPresent(MachineEnvDO::getDescription, machineEnvVO.getDescription()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cd.casic.module.machine.dal.mysql;
|
||||
|
||||
import cd.casic.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cd.casic.module.machine.dal.dataobject.MachineEnvDO;
|
||||
import cd.casic.module.machine.dal.dataobject.MachineInfo;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface MachineInfoMapper extends BaseMapperX<MachineInfo> {
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
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<MachineProxyDO> {
|
||||
|
||||
|
||||
|
||||
default PageResult<MachineProxyDO> selectPage(MachineProxyVO machineProxyVO) {
|
||||
return selectPage(machineProxyVO, new LambdaQueryWrapperX<MachineProxyDO>()
|
||||
.eqIfPresent(MachineProxyDO::getHostIp, machineProxyVO.getHostIp())
|
||||
.eqIfPresent(MachineProxyDO::getProxyType, machineProxyVO.getProxyType())
|
||||
.eqIfPresent(MachineProxyDO::getStatus, machineProxyVO.getStatus())
|
||||
.likeIfPresent(MachineProxyDO::getDescription, machineProxyVO.getDescription())
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package cd.casic.module.machine.dal.mysql;
|
||||
|
||||
import cd.casic.module.machine.dal.dataobject.SecretKey;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SecretServiceMapper extends BaseMapper<SecretKey> {
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cd.casic.module.machine.enums;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AuthenticationType implements CodeEnum {
|
||||
PASSWORD(1,"密码认证"),
|
||||
SECRET_KEY(2,"密钥认证");
|
||||
|
||||
private final int code;
|
||||
|
||||
private final String message;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package cd.casic.module.machine.enums;
|
||||
|
||||
public interface CodeEnum {
|
||||
int getCode();
|
||||
|
||||
String getMessage();
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package cd.casic.module.machine.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 连接状态枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ConnectionStatus {
|
||||
DISCONNECTED("断开连接"),
|
||||
CONNECTING("正在连接"),
|
||||
CONNECTED("已连接"),
|
||||
AUTH_FAILED("认证失败"),
|
||||
CONNECTION_TIMEOUT("连接超时"),
|
||||
CONNECTION_ERROR("连接错误"),
|
||||
CLOSED("已关闭");
|
||||
|
||||
private final String description;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cd.casic.module.machine.enums;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MachineInfoStatus implements CodeEnum {
|
||||
ENABLE(1,"启用"),
|
||||
UN_ENABLE(0,"停用");
|
||||
|
||||
private final int code;
|
||||
|
||||
private final String message;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cd.casic.module.machine.enums;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MachineInfoType implements CodeEnum {
|
||||
Linux(1,"Linux"),
|
||||
WINDOWS(2,"Windows");
|
||||
|
||||
private final int code;
|
||||
|
||||
private final String message;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
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 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package cd.casic.module.machine.enums;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PermissionExceptionEnum implements CodeEnum {
|
||||
URL_NOT_EXIST(1, "资源路径不存在,请检查请求地址"),
|
||||
|
||||
NO_PERMISSION(2, "没有权限访问资源,请联系管理员"),
|
||||
|
||||
NO_PERMISSION_OPERATE(3, "没有权限操作该数据,请联系管理员");
|
||||
|
||||
private final int code;
|
||||
|
||||
private final String message;
|
||||
}
|
@ -0,0 +1,639 @@
|
||||
//package cd.casic.module.machine.handler;
|
||||
//import cd.casic.module.machine.utils.AliYunOssClient;
|
||||
//import cd.casic.module.machine.dal.dataobject.MachineInfo;
|
||||
//import cd.casic.module.machine.dal.dataobject.SecretKey;
|
||||
//import cd.casic.module.machine.enums.ConnectionStatus;
|
||||
//import cd.casic.module.machine.service.SecretKeyService;
|
||||
//import com.jcraft.jsch.*;
|
||||
//import jakarta.annotation.Resource;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//import org.springframework.util.StreamUtils;
|
||||
//import org.springframework.util.StringUtils;
|
||||
//import java.io.*;
|
||||
//import java.nio.charset.StandardCharsets;
|
||||
//import java.util.Objects;
|
||||
//import java.util.Properties;
|
||||
//import java.util.concurrent.atomic.AtomicBoolean;
|
||||
//
|
||||
///**
|
||||
// * 优化后的SSH连接会话类
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Component
|
||||
//public class ConnectionSession implements AutoCloseable {
|
||||
// @Resource
|
||||
// SecretKeyService secretKeyService;
|
||||
//
|
||||
// @Resource
|
||||
// AliYunOssClient aliYunOssClient;
|
||||
//
|
||||
// private MachineInfo machineInfo;
|
||||
// private Session sshSession;
|
||||
// private ConnectionStatus status = ConnectionStatus.DISCONNECTED;
|
||||
// private final AtomicBoolean isExecuting = new AtomicBoolean(false);
|
||||
//
|
||||
// // todo连接配置常量
|
||||
// private static final int CONNECTION_TIMEOUT = 5000; // 连接超时时间(毫秒)
|
||||
// private static final int COMMAND_TIMEOUT = 30000; // 命令执行超时时间(毫秒)
|
||||
// private static final int RETRY_COUNT = 3; // 重试次数
|
||||
// private static final int RETRY_DELAY = 1000; // 重试间隔(毫秒)
|
||||
//
|
||||
// public ConnectionSession() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // 使用setter注入MachineInfo
|
||||
// public void setMachineInfo(MachineInfo machineInfo) {
|
||||
// this.machineInfo = Objects.requireNonNull(machineInfo, "MachineInfo cannot be null");
|
||||
// log.debug("MachineInfo 已注入: {}", machineInfo.getHostIp());
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 建立SSH连接,支持重试机制
|
||||
// */
|
||||
// public synchronized void connect() throws JSchException {
|
||||
// if (status == ConnectionStatus.CONNECTED) {
|
||||
// log.debug("Already connected to {}", machineInfo.getHostIp());
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// status = ConnectionStatus.CONNECTING;
|
||||
// JSchException lastException = null;
|
||||
//
|
||||
// for (int attempt = 1; attempt <= RETRY_COUNT; attempt++) {
|
||||
// try {
|
||||
// doConnect();
|
||||
// status = ConnectionStatus.CONNECTED;
|
||||
// log.info("SSH connection established successfully to {} (attempt {}/{})",
|
||||
// machineInfo.getHostIp(), attempt, RETRY_COUNT);
|
||||
// return;
|
||||
// } catch (JSchException e) {
|
||||
// lastException = e;
|
||||
// status = ConnectionStatus.CONNECTION_ERROR;
|
||||
// log.error("SSH connection attempt {}/{} failed: {}",
|
||||
// attempt, RETRY_COUNT, e.getMessage());
|
||||
//
|
||||
// // 认证失败直接退出,无需重试
|
||||
// if (e.getMessage().contains("Auth fail")) {
|
||||
// status = ConnectionStatus.AUTH_FAILED;
|
||||
// throw e;
|
||||
// }
|
||||
//
|
||||
// // 重试前等待
|
||||
// if (attempt < RETRY_COUNT) {
|
||||
// try {
|
||||
// Thread.sleep(RETRY_DELAY);
|
||||
// } catch (InterruptedException ie) {
|
||||
// Thread.currentThread().interrupt();
|
||||
// throw new JSchException("Connection attempt interrupted", ie);
|
||||
// }
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 所有重试都失败
|
||||
// throw new JSchException("Failed to connect after " + RETRY_COUNT + " attempts", lastException);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实际执行连接逻辑
|
||||
// */
|
||||
// private void doConnect() throws JSchException, IOException {
|
||||
// JSch jsch = new JSch();
|
||||
//
|
||||
// // 配置认证方式
|
||||
// configureAuthentication(jsch);
|
||||
//
|
||||
// // 创建SSH会话
|
||||
// sshSession = jsch.getSession(
|
||||
// machineInfo.getUsername(),
|
||||
// machineInfo.getHostIp(),
|
||||
// machineInfo.getSshPort() != null ? machineInfo.getSshPort() : 22
|
||||
// );
|
||||
//
|
||||
// // 配置连接参数
|
||||
// configureSession(sshSession);
|
||||
//
|
||||
// // 建立连接
|
||||
// sshSession.connect(CONNECTION_TIMEOUT);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 配置认证方式(密码或密钥)
|
||||
// */
|
||||
// private void configureAuthentication(JSch jsch) throws JSchException {
|
||||
// if (machineInfo.getAuthenticationTypeCode() == 2) {
|
||||
// // 密钥认证
|
||||
// if (machineInfo.getSecretKeyId() == null) {
|
||||
// throw new JSchException("Secret key ID is required for key-based authentication");
|
||||
// }
|
||||
//
|
||||
// String privateKeyContent = getPrivateKeyContent(machineInfo.getSecretKeyId());
|
||||
// // 验证私钥格式
|
||||
// if (!privateKeyContent.startsWith("-----BEGIN")) {
|
||||
// throw new JSchException("Invalid private key format. Expected OpenSSH format.");
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// // 尝试加载私钥
|
||||
// jsch.addIdentity(
|
||||
// machineInfo.getName(),
|
||||
// privateKeyContent.getBytes(StandardCharsets.UTF_8),
|
||||
// null,
|
||||
// null
|
||||
// );
|
||||
// log.info("Private key loaded successfully for {}", machineInfo.getHostIp());
|
||||
// } catch (JSchException e) {
|
||||
// log.error("Failed to load private key: {}", e.getMessage());
|
||||
// throw e;
|
||||
// }
|
||||
// } else if (machineInfo.getAuthenticationTypeCode() == 1) {
|
||||
// // 密码认证
|
||||
// if (StringUtils.isEmpty(machineInfo.getPassword())) {
|
||||
// throw new JSchException("Password is required for password-based authentication");
|
||||
// }
|
||||
// } else {
|
||||
// throw new JSchException("Unsupported authentication type: " + machineInfo.getAuthenticationType());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 配置SSH会话参数(安全增强)
|
||||
// */
|
||||
// private void configureSession(Session session) {
|
||||
// Properties config = new Properties();
|
||||
//
|
||||
// // 安全增强:默认验证主机密钥
|
||||
// if (isTrustedEnvironment()) {
|
||||
// log.warn("Running in trusted environment - disabling strict host key checking for {}",
|
||||
// machineInfo.getHostIp());
|
||||
// config.put("StrictHostKeyChecking", "no");
|
||||
// } else {
|
||||
// config.put("StrictHostKeyChecking", "yes");
|
||||
// // 可选:配置已知主机文件路径
|
||||
// //直接配置阿里云密钥地址
|
||||
// config.put("UserKnownHostsFile", secretKeyService.getById(machineInfo.getSecretKeyId()).getPath());
|
||||
// }
|
||||
//
|
||||
// // 其他安全配置
|
||||
// config.put("PreferredAuthentications", "publicKey,password,keyboard-interactive");
|
||||
// config.put("ServerAliveInterval", "30"); // 每30秒发送一次心跳
|
||||
// config.put("ServerAliveCountMax", "3"); // 允许3次心跳失败
|
||||
//
|
||||
// session.setConfig(config);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 判断是否为可信环境(生产环境应返回false)
|
||||
// */
|
||||
// private boolean isTrustedEnvironment() {
|
||||
// // todo实际项目中应基于配置或环境变量判断
|
||||
// return System.getProperty("environment", "production").equalsIgnoreCase("development");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public synchronized void close() {
|
||||
// disconnect();
|
||||
// }
|
||||
//
|
||||
// public synchronized void disconnect() {
|
||||
// if (sshSession != null && sshSession.isConnected()) {
|
||||
// try {
|
||||
// sshSession.disconnect();
|
||||
// log.info("SSH connection closed: {}", machineInfo.getHostIp());
|
||||
// } catch (Exception e) {
|
||||
// log.error("Error closing SSH session: {}", e.getMessage());
|
||||
// }
|
||||
// }
|
||||
// status = ConnectionStatus.DISCONNECTED;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 执行远程命令,支持超时和中断处理
|
||||
// */
|
||||
// public String executeCommand(String command) throws JSchException, IOException {
|
||||
// if (!isConnected()) {
|
||||
// throw new IllegalStateException("Session is not connected");
|
||||
// }
|
||||
//
|
||||
// if (!isExecuting.compareAndSet(false, true)) {
|
||||
// throw new IllegalStateException("Another command is already executing");
|
||||
// }
|
||||
//
|
||||
// Channel channel = null;
|
||||
// InputStream inputStream = null;
|
||||
// ByteArrayOutputStream outputStream = null;
|
||||
//
|
||||
// try {
|
||||
// channel = createExecChannel(command);
|
||||
// inputStream = channel.getInputStream();
|
||||
// outputStream = new ByteArrayOutputStream();
|
||||
//
|
||||
// // 连接通道并设置超时
|
||||
// channel.connect(COMMAND_TIMEOUT);
|
||||
//
|
||||
// // 读取命令输出
|
||||
// return readCommandOutput(inputStream, outputStream, channel);
|
||||
// } catch (InterruptedException e) {
|
||||
// Thread.currentThread().interrupt();
|
||||
// throw new IOException("Command execution interrupted", e);
|
||||
// } finally {
|
||||
// // 释放资源
|
||||
// closeResources(channel, inputStream, outputStream);
|
||||
// isExecuting.set(false);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 创建并配置命令执行通道
|
||||
// */
|
||||
// private Channel createExecChannel(String command) throws JSchException {
|
||||
// Channel channel = sshSession.openChannel("exec");
|
||||
// ((ChannelExec) channel).setCommand(command);
|
||||
//
|
||||
// // 配置通道
|
||||
// channel.setInputStream(null);
|
||||
// ((ChannelExec) channel).setErrStream(new ByteArrayOutputStream()); // 捕获错误输出
|
||||
//
|
||||
// return channel;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 读取命令输出
|
||||
// */
|
||||
// private String readCommandOutput(InputStream inputStream,
|
||||
// ByteArrayOutputStream outputStream,
|
||||
// Channel channel) throws IOException, InterruptedException {
|
||||
// byte[] buffer = new byte[1024];
|
||||
//
|
||||
//
|
||||
// // 使用线程中断机制实现超时控制
|
||||
// Thread readerThread = new Thread(() -> {
|
||||
// int bytesRead;
|
||||
// try {
|
||||
// while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
// outputStream.write(buffer, 0, bytesRead);
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// // 通道关闭或读取异常
|
||||
// if (channel.isConnected()) {
|
||||
// log.warn("Error reading command output: {}", e.getMessage());
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// readerThread.start();
|
||||
//
|
||||
// // 等待命令执行完成或超时
|
||||
// readerThread.join(COMMAND_TIMEOUT);
|
||||
//
|
||||
// // 如果线程仍在运行,中断并关闭通道
|
||||
// if (readerThread.isAlive()) {
|
||||
// readerThread.interrupt();
|
||||
// channel.disconnect();
|
||||
// throw new IOException("Command execution timed out after " + COMMAND_TIMEOUT + "ms");
|
||||
// }
|
||||
//
|
||||
// // 等待通道完全关闭
|
||||
// while (channel.isConnected()) {
|
||||
// Thread.sleep(100);
|
||||
// }
|
||||
//
|
||||
// return outputStream.toString(StandardCharsets.UTF_8);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 关闭资源
|
||||
// */
|
||||
// private void closeResources(Channel channel, InputStream inputStream, OutputStream outputStream) {
|
||||
// if (outputStream != null) {
|
||||
// try {
|
||||
// outputStream.close();
|
||||
// } catch (IOException e) {
|
||||
// log.warn("Error closing output stream: {}", e.getMessage());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (inputStream != null) {
|
||||
// try {
|
||||
// inputStream.close();
|
||||
// } catch (IOException e) {
|
||||
// log.warn("Error closing input stream: {}", e.getMessage());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (channel != null && channel.isConnected()) {
|
||||
// channel.disconnect();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 上传文件到远程服务器
|
||||
// */
|
||||
// public boolean uploadFile(String localFilePath, String remoteFilePath) throws IOException {
|
||||
// if (!isConnected()) {
|
||||
// throw new IllegalStateException("Cannot upload file: SSH session is not connected");
|
||||
// }
|
||||
//
|
||||
// // 检查本地文件是否存在且可读
|
||||
// File localFile = new File(localFilePath);
|
||||
// if (!localFile.exists()) {
|
||||
// throw new FileNotFoundException("Local file not found: " + localFilePath);
|
||||
// }
|
||||
// if (!localFile.canRead()) {
|
||||
// throw new IOException("Cannot read local file: " + localFilePath);
|
||||
// }
|
||||
//
|
||||
// ChannelSftp channel = null;
|
||||
// boolean uploadSuccess = false;
|
||||
//
|
||||
// try {
|
||||
// // 创建并连接SFTP通道,设置超时
|
||||
// channel = (ChannelSftp) sshSession.openChannel("sftp");
|
||||
// channel.connect(CONNECTION_TIMEOUT);
|
||||
//
|
||||
// // 确保目标目录存在
|
||||
// createRemoteDirectoryIfNotExists(channel, getParentDirectory(remoteFilePath));
|
||||
//
|
||||
// // 使用更健壮的上传方式
|
||||
// channel.put(
|
||||
// new FileInputStream(localFile),
|
||||
// remoteFilePath,
|
||||
// new ProgressMonitorAdapter(localFile.length()),
|
||||
// ChannelSftp.OVERWRITE
|
||||
// );
|
||||
//
|
||||
// uploadSuccess = true;
|
||||
// log.info("File uploaded successfully: {} -> {}", localFilePath, remoteFilePath);
|
||||
// return true;
|
||||
//
|
||||
// } catch (SftpException e) {
|
||||
// log.error("SFTP error during file upload ({} -> {}): {}",
|
||||
// localFilePath, remoteFilePath, e.getMessage(), e);
|
||||
// throw new IOException("SFTP error: " + e.getMessage(), e);
|
||||
// } catch (FileNotFoundException e) {
|
||||
// log.error("Local file not found during upload: {}", localFilePath, e);
|
||||
// throw e;
|
||||
// } catch (IOException e) {
|
||||
// log.error("IO error during file upload: {}", e.getMessage(), e);
|
||||
// throw e;
|
||||
// } catch (Exception e) {
|
||||
// log.error("Unexpected error during file upload: {}", e.getMessage(), e);
|
||||
// throw new IOException("Unexpected error: " + e.getMessage(), e);
|
||||
// } finally {
|
||||
// // 确保通道始终被关闭
|
||||
// disconnectChannel(channel);
|
||||
//
|
||||
//// // 如果上传失败,尝试删除不完整的文件
|
||||
//// if (!uploadSuccess && remoteFilePath != null && !remoteFilePath.isEmpty()) {
|
||||
//// tryDeleteIncompleteFile(remoteFilePath);
|
||||
//// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public boolean downloadFile(String remoteFilePath, String localFilePath) throws IOException {
|
||||
// if (!isConnected()) {
|
||||
// throw new IllegalStateException("Cannot download file: SSH session is not connected");
|
||||
// }
|
||||
//
|
||||
// // 检查本地目录是否存在且可写
|
||||
// File localFile = new File(localFilePath);
|
||||
// File parentDir = localFile.getParentFile();
|
||||
// if (parentDir != null && !parentDir.exists()) {
|
||||
// if (!parentDir.mkdirs()) {
|
||||
// throw new IOException("Failed to create local directory: " + parentDir.getAbsolutePath());
|
||||
// }
|
||||
// }
|
||||
// if (parentDir != null && !parentDir.canWrite()) {
|
||||
// throw new IOException("Cannot write to local directory: " + parentDir.getAbsolutePath());
|
||||
// }
|
||||
//
|
||||
// ChannelSftp channel = null;
|
||||
// boolean downloadSuccess = false;
|
||||
// File tempFile = null;
|
||||
//
|
||||
// try {
|
||||
// // 创建并连接SFTP通道,设置超时
|
||||
// channel = (ChannelSftp) sshSession.openChannel("sftp");
|
||||
// channel.connect(CONNECTION_TIMEOUT);
|
||||
//
|
||||
// // 检查远程文件是否存在
|
||||
// SftpATTRS attrs = channel.stat(remoteFilePath);
|
||||
// long fileSize = attrs.getSize();
|
||||
//
|
||||
// // 使用临时文件避免部分下载覆盖完整文件
|
||||
// tempFile = new File(localFilePath + ".part");
|
||||
//
|
||||
// // 执行下载并监控进度
|
||||
// channel.get(
|
||||
// remoteFilePath,
|
||||
// new FileOutputStream(tempFile).toString(),
|
||||
// new ProgressMonitorAdapter(fileSize),
|
||||
// ChannelSftp.OVERWRITE
|
||||
// );
|
||||
//
|
||||
// // 验证下载完整性
|
||||
// if (tempFile.length() != fileSize) {
|
||||
// throw new IOException("Download incomplete: expected " + fileSize +
|
||||
// " bytes, but got " + tempFile.length() + " bytes");
|
||||
// }
|
||||
//
|
||||
// // 重命名临时文件为目标文件(原子操作)
|
||||
// if (!tempFile.renameTo(localFile)) {
|
||||
// throw new IOException("Failed to rename temporary file to: " + localFilePath);
|
||||
// }
|
||||
//
|
||||
// downloadSuccess = true;
|
||||
// log.info("File downloaded successfully: {} -> {}", remoteFilePath, localFilePath);
|
||||
// return true;
|
||||
//
|
||||
// } catch (SftpException e) {
|
||||
// log.error("SFTP error during file download ({} -> {}): {}",
|
||||
// remoteFilePath, localFilePath, e.getMessage(), e);
|
||||
// if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
|
||||
// throw new FileNotFoundException("Remote file not found: " + remoteFilePath);
|
||||
// }
|
||||
// throw new IOException("SFTP error: " + e.getMessage(), e);
|
||||
// } catch (IOException e) {
|
||||
// log.error("IO error during file download: {}", e.getMessage(), e);
|
||||
// throw e;
|
||||
// } catch (Exception e) {
|
||||
// log.error("Unexpected error during file download: {}", e.getMessage(), e);
|
||||
// throw new IOException("Unexpected error: " + e.getMessage(), e);
|
||||
// } finally {
|
||||
// // 确保通道始终被关闭
|
||||
// disconnectChannel(channel);
|
||||
//
|
||||
// // 如果下载失败,清理临时文件
|
||||
// if (!downloadSuccess && tempFile != null && tempFile.exists()) {
|
||||
// if (tempFile.delete()) {
|
||||
// log.debug("Deleted incomplete temporary file: {}", tempFile.getAbsolutePath());
|
||||
// } else {
|
||||
// log.warn("Failed to delete incomplete temporary file: {}", tempFile.getAbsolutePath());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 创建远程目录(如果不存在)
|
||||
// private void createRemoteDirectoryIfNotExists(ChannelSftp channel, String directory) throws SftpException {
|
||||
// if (directory == null || directory.isEmpty() || directory.equals("/")) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// channel.stat(directory);
|
||||
// } catch (SftpException e) {
|
||||
// // 目录不存在,尝试创建
|
||||
// createRemoteDirectoryIfNotExists(channel, getParentDirectory(directory));
|
||||
// channel.mkdir(directory);
|
||||
// log.debug("Created remote directory: {}", directory);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 获取路径的父目录
|
||||
// private String getParentDirectory(String path) {
|
||||
// int lastSlash = path.lastIndexOf('/');
|
||||
// return lastSlash > 0 ? path.substring(0, lastSlash) : "";
|
||||
// }
|
||||
//
|
||||
// // 断开SFTP通道
|
||||
// private void disconnectChannel(Channel channel) {
|
||||
// if (channel != null && channel.isConnected()) {
|
||||
// try {
|
||||
// channel.disconnect();
|
||||
// log.debug("SFTP channel disconnected");
|
||||
// } catch (Exception e) {
|
||||
// log.warn("Error disconnecting SFTP channel: {}", e.getMessage());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 尝试删除不完整的文件
|
||||
// private void tryDeleteIncompleteFile(String remoteFilePath) {
|
||||
// ChannelSftp channel = null;
|
||||
// try {
|
||||
// channel = (ChannelSftp) sshSession.openChannel("sftp");
|
||||
// channel.connect(CONNECTION_TIMEOUT);
|
||||
// channel.rm(remoteFilePath);
|
||||
// log.info("Deleted incomplete file: {}", remoteFilePath);
|
||||
// } catch (Exception e) {
|
||||
// log.warn("Failed to delete incomplete file {}: {}", remoteFilePath, e.getMessage());
|
||||
// } finally {
|
||||
// disconnectChannel(channel);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 增强的进度监控器
|
||||
// private static class ProgressMonitorAdapter implements SftpProgressMonitor {
|
||||
// private final long totalBytes;
|
||||
// private long bytesWritten = 0;
|
||||
// private int lastProgress = 0;
|
||||
// private final long startTime = System.currentTimeMillis();
|
||||
//
|
||||
// public ProgressMonitorAdapter(long totalBytes) {
|
||||
// this.totalBytes = totalBytes;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean count(long count) {
|
||||
// bytesWritten += count;
|
||||
//
|
||||
// // 计算进度百分比
|
||||
// int progress = (int) ((bytesWritten * 100) / totalBytes);
|
||||
//
|
||||
// // 每10%或每秒更新一次日志
|
||||
// long elapsedTime = System.currentTimeMillis() - startTime;
|
||||
// if (progress - lastProgress >= 10 || elapsedTime >= 1000) {
|
||||
// double speed = bytesWritten / (elapsedTime / 1000.0);
|
||||
// String speedStr = formatTransferSpeed(speed);
|
||||
//
|
||||
// log.debug("Upload progress: {}% ({}/{} bytes, {})",
|
||||
// progress, bytesWritten, totalBytes, speedStr);
|
||||
// lastProgress = progress;
|
||||
// }
|
||||
//
|
||||
// return true; // 返回true继续传输,返回false中断传输
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void end() {
|
||||
// long elapsedTime = System.currentTimeMillis() - startTime;
|
||||
// double speed = totalBytes / (elapsedTime / 1000.0);
|
||||
// String speedStr = formatTransferSpeed(speed);
|
||||
//
|
||||
// log.info("Upload completed: {} bytes in {} ms (avg speed: {})",
|
||||
// totalBytes, elapsedTime, speedStr);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void init(int op, String src, String dest, long max) {
|
||||
// log.info("Starting upload: {} -> {} ({} bytes)", src, dest, max);
|
||||
// }
|
||||
//
|
||||
// // 格式化传输速度
|
||||
// private String formatTransferSpeed(double bytesPerSecond) {
|
||||
// String[] units = {"B/s", "KB/s", "MB/s", "GB/s"};
|
||||
// int unitIndex = 0;
|
||||
//
|
||||
// while (bytesPerSecond >= 1024 && unitIndex < units.length - 1) {
|
||||
// bytesPerSecond /= 1024;
|
||||
// unitIndex++;
|
||||
// }
|
||||
//
|
||||
// return String.format("%.2f %s", bytesPerSecond, units[unitIndex]);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 检查连接状态
|
||||
// */
|
||||
// public ConnectionStatus getStatus() {
|
||||
// if (status == ConnectionStatus.CONNECTED &&
|
||||
// (sshSession == null || !sshSession.isConnected())) {
|
||||
// status = ConnectionStatus.DISCONNECTED;
|
||||
// }
|
||||
// return status;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 检查是否已连接
|
||||
// */
|
||||
// public boolean isConnected() {
|
||||
// return status == ConnectionStatus.CONNECTED &&
|
||||
// sshSession != null &&
|
||||
// sshSession.isConnected();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// private String getPrivateKeyContent(Long secretKeyId) {
|
||||
// if (secretKeyId == null) {
|
||||
// return null;
|
||||
// }
|
||||
// SecretKey secretKey = secretKeyService.getById(secretKeyId);
|
||||
// byte[] content;
|
||||
// try {
|
||||
// content = aliYunOssClient.getContent(secretKey.getPath().substring(secretKey.getPath().lastIndexOf("/") + 1));
|
||||
// } catch (Exception e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
//
|
||||
// //改为S3FileClient读取
|
||||
// InputStream read = new ByteArrayInputStream(content);
|
||||
//
|
||||
// try {
|
||||
// return StreamUtils.copyToString(read, StandardCharsets.UTF_8);
|
||||
// } catch (IOException e) {
|
||||
// log.error("读取私钥文件失败", e);
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//}
|
@ -0,0 +1,44 @@
|
||||
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<MachineEnvDO> getEnvPage(@Valid MachineEnvVO machineEnvVO);
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*/
|
||||
void deleteEnvList(String ids);
|
||||
|
||||
/*
|
||||
* 修改环境变量
|
||||
*/
|
||||
void updateEnv(@Valid MachineEnvVO machineEnvVO);
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package cd.casic.module.machine.service;
|
||||
|
||||
import cd.casic.framework.commons.pojo.PageResult;
|
||||
import cd.casic.module.machine.controller.vo.MachineInfoDto;
|
||||
import cd.casic.module.machine.dal.dataobject.MachineInfo;
|
||||
import cd.casic.module.machine.enums.ConnectionStatus;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface MachineInfoService {
|
||||
boolean addMachineInfo(MachineInfoDto MachineInfoDto);
|
||||
|
||||
PageResult<MachineInfoDto> listMachineInfo(MachineInfoDto MachineInfoDto);
|
||||
|
||||
boolean updateMachineInfo(MachineInfoDto machineInfoDto);
|
||||
|
||||
boolean updateStatus(MachineInfoDto machineInfoDto);
|
||||
|
||||
boolean bindingSecretKey(MachineInfoDto machineInfoDto);
|
||||
|
||||
void deleteList(String machineInfoIds);
|
||||
|
||||
void deleteMachineInfo(Long machineInfoId);
|
||||
|
||||
|
||||
/**
|
||||
* 测试机器连接
|
||||
*
|
||||
* @param id 机器id
|
||||
* @return 连接是否成功
|
||||
*/
|
||||
boolean testConnection(Long id);
|
||||
|
||||
/**
|
||||
* 获取机器连接状态
|
||||
*
|
||||
* @param machineName 机器名称
|
||||
* @return 连接状态
|
||||
*/
|
||||
ConnectionStatus getConnectionStatus(String machineName);
|
||||
|
||||
/**
|
||||
* 获取所有连接状态
|
||||
*
|
||||
* @return 机器名称到连接状态的映射
|
||||
*/
|
||||
Map<String, ConnectionStatus> getAllConnectionStatus();
|
||||
|
||||
/**
|
||||
* 建立机器连接
|
||||
*
|
||||
* @param machineInfo 机器信息
|
||||
* @return 连接会话ID
|
||||
*/
|
||||
String connect(MachineInfo machineInfo);
|
||||
|
||||
/**
|
||||
* 断开机器连接
|
||||
*
|
||||
* @param sessionId 会话ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
boolean disconnect(String sessionId);
|
||||
|
||||
/**
|
||||
* 执行远程命令
|
||||
*
|
||||
* @param sessionId 会话ID
|
||||
* @param command 命令
|
||||
* @return 命令执行结果
|
||||
*/
|
||||
String executeCommand(String sessionId, String command);
|
||||
|
||||
/**
|
||||
* 上传文件到远程机器
|
||||
*
|
||||
* @param sessionId 会话ID
|
||||
* @param localFilePath 本地文件路径
|
||||
* @param remoteFilePath 远程文件路径
|
||||
* @return 操作结果
|
||||
*/
|
||||
boolean uploadFile(String sessionId, String localFilePath, String remoteFilePath);
|
||||
|
||||
/**
|
||||
* 从远程机器下载文件
|
||||
*
|
||||
* @param sessionId 会话ID
|
||||
* @param remoteFilePath 远程文件路径
|
||||
* @param localFilePath 本地文件路径
|
||||
* @return 操作结果
|
||||
*/
|
||||
boolean downloadFile(String sessionId, String remoteFilePath, String localFilePath);
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
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 java.util.Map;
|
||||
|
||||
/**
|
||||
* 机器代理服务接口
|
||||
*/
|
||||
public interface MachineProxyService {
|
||||
/**
|
||||
* 注册新的机器代理
|
||||
*/
|
||||
Long createProxy(MachineProxyVO machineProxyVO);
|
||||
|
||||
/**
|
||||
* 更新代理状态
|
||||
*/
|
||||
void updateProxy(MachineProxyVO machineProxyVO);
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有代理的状态统计
|
||||
*
|
||||
* @return 状态统计Map
|
||||
*/
|
||||
Map<Integer, Long> getAllProxyStatus();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 批量删除代理
|
||||
*
|
||||
* @param proxyIds 代理ID列表
|
||||
*/
|
||||
void deleteProxyList(String proxyIds);
|
||||
|
||||
PageResult<MachineProxyDO> getProxyPage(MachineProxyVO machineProxyVO);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cd.casic.module.machine.service;
|
||||
|
||||
import cd.casic.framework.commons.pojo.PageResult;
|
||||
import cd.casic.module.machine.dal.dataobject.SecretKey;
|
||||
import cd.casic.module.machine.controller.vo.SecretKeyDto;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SecretKeyService extends IService<SecretKey> {
|
||||
boolean addSecretKey(SecretKeyDto secretKeyDto) throws Exception;
|
||||
|
||||
void bindingMachine(Long secretKeyId, List<Long> machineInfoIds);
|
||||
|
||||
boolean updateSecretKey(SecretKeyDto secretKeyDto);
|
||||
|
||||
|
||||
PageResult<SecretKey> listSecretKey(SecretKeyDto secretKeyDto);
|
||||
|
||||
|
||||
|
||||
boolean deleteList(List<Long> secretKeyIds);
|
||||
}
|
||||
|
@ -0,0 +1,108 @@
|
||||
package cd.casic.module.machine.service.impl;
|
||||
import cd.casic.module.machine.convert.MachineEnvConvert;
|
||||
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) {
|
||||
if (machineId == null) {
|
||||
return null;
|
||||
}
|
||||
MachineEnvDO machineEnvDO = machineEnvMapper.selectById(machineId);
|
||||
return machineEnvDO != null ? MachineEnvConvert.INSTANCE.convertToVO(machineEnvDO) : null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PageResult<MachineEnvDO> getEnvPage(MachineEnvVO machineEnvVO) {
|
||||
return machineEnvMapper.selectPage(machineEnvVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteEnvList(String ids) {
|
||||
//ids转换为List,使用流
|
||||
List<Long> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
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 cd.casic.module.machine.utils.EnumUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
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;
|
||||
import static org.apache.catalina.security.SecurityUtil.remove;
|
||||
|
||||
/**
|
||||
* 机器代理服务实现类
|
||||
*/
|
||||
@Service
|
||||
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 Map<Integer, Long> getAllProxyStatus() {
|
||||
List<MachineProxyDO> 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<Long> machineProxyIds = Arrays.stream(ids.split(","))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.map(Long::parseLong)
|
||||
.toList();
|
||||
//检查是否存在在线的代理
|
||||
validateMachineProxyOnline(machineProxyIds);
|
||||
// 批量逻辑删除
|
||||
machineProxyMapper.deleteBatchIds(machineProxyIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<MachineProxyDO> getProxyPage(MachineProxyVO machineProxyVO) {
|
||||
return machineProxyMapper.selectPage(machineProxyVO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
MachineProxyDO validateMachineProxyExists(Long id) {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
MachineProxyDO machineProxyDO = machineProxyMapper.selectById(id);
|
||||
if (machineProxyDO == null) {
|
||||
throw exception(MACHINE_PROXY_NOT_EXISTS);
|
||||
}
|
||||
return machineProxyDO;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateMachineProxyOnline(List<Long> ids) {
|
||||
List<MachineProxyDO> machineProxyDOS = machineProxyMapper.selectBatchIds(ids);
|
||||
List<Long>onlineId=new ArrayList<>();
|
||||
machineProxyDOS.forEach(machineProxyDO->{
|
||||
if (machineProxyDO.getStatus() == MachineProxyStatus.ONLINE.getCode()) {
|
||||
onlineId.add(machineProxyDO.getId());
|
||||
}
|
||||
});
|
||||
if(!onlineId.isEmpty()){
|
||||
throw exception(MACHINE_PROXY_IS_ONLINE,onlineId);
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,354 @@
|
||||
//package cd.casic.module.machine.service.impl;
|
||||
//import cd.casic.module.machine.enums.MachineInfoType;
|
||||
//import cd.casic.module.machine.handler.ConnectionSession;
|
||||
//import cd.casic.module.machine.dal.mysql.MachineInfoMapper;
|
||||
//import cd.casic.module.machine.controller.vo.MachineInfoDto;
|
||||
//import cd.casic.module.machine.dal.dataobject.MachineInfo;
|
||||
//import cd.casic.module.machine.enums.AuthenticationType;
|
||||
//import cd.casic.module.machine.enums.ConnectionStatus;
|
||||
//import cd.casic.module.machine.enums.MachineInfoStatus;
|
||||
//import cd.casic.module.machine.service.MachineInfoService;
|
||||
//import cd.casic.module.machine.utils.EnumUtils;
|
||||
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
//import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
//import jakarta.annotation.Resource;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.beans.BeanUtils;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//import java.util.Arrays;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//import java.util.concurrent.ConcurrentHashMap;
|
||||
//import java.util.concurrent.atomic.AtomicInteger;
|
||||
//import java.util.stream.Collectors;
|
||||
//
|
||||
//@Slf4j
|
||||
//@Service("machineInfoService")
|
||||
//public class MachineinfoServiceImpl implements MachineInfoService {
|
||||
//
|
||||
// int ENABLE = 1;
|
||||
// int UN_ENABLE = 0;
|
||||
//
|
||||
// @Resource
|
||||
// private MachineInfoMapper machineInfoMapper;
|
||||
// @Resource
|
||||
// private ConnectionSession connectionSession;
|
||||
// /**
|
||||
// * 会话ID生成器
|
||||
// */
|
||||
// private final AtomicInteger sessionIdGenerator = new AtomicInteger(1000);
|
||||
//
|
||||
// /**
|
||||
// * 会话管理:会话ID -> 连接会话
|
||||
// */
|
||||
// private final Map<String, ConnectionSession> sessions = new ConcurrentHashMap<>();
|
||||
//
|
||||
// /**
|
||||
// * 机器名称 -> 会话ID
|
||||
// */
|
||||
// private final Map<String, String> machineSessionMapping = new ConcurrentHashMap<>();
|
||||
//
|
||||
// @Override
|
||||
// public boolean addMachineInfo(MachineInfoDto machineInfoDto) {
|
||||
// if (machineInfoDto == null) {
|
||||
// throw new ServiceException(ServiceException.MACHINE_INFO_NULL, "机器信息为空");
|
||||
// }
|
||||
// MachineInfo machineInfo = new MachineInfo();
|
||||
// BeanUtils.copyProperties(machineInfoDto, machineInfo);
|
||||
// machineInfo.setStatusCode(1);
|
||||
// machineInfo.setAuthenticationTypeCode(
|
||||
// "密码认证".equals(machineInfoDto.getAuthenticationType())
|
||||
// ? AuthenticationType.PASSWORD.getCode()
|
||||
// : AuthenticationType.SECRET_KEY.getCode()
|
||||
// );
|
||||
// machineInfo.setMachineInfoTypeCode(
|
||||
// "Windows".equals(machineInfoDto.getMachineInfoType())
|
||||
// ? MachineInfoType.WINDOWS.getCode()
|
||||
// : MachineInfoType.Linux.getCode()
|
||||
// );
|
||||
//
|
||||
// return this.save(machineInfo);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public PageResult<MachineInfoDto> listMachineInfo(MachineInfoDto machineInfoDto) {
|
||||
// QueryWrapper<MachineInfo> queryWrapper = getMachineInfoQueryWrapper(machineInfoDto);
|
||||
// Page<MachineInfo> page = machineInfoMapper.selectPage(
|
||||
// new Page<>(machineInfoDto.getPageIndex(), machineInfoDto.getPageSize()),
|
||||
// queryWrapper
|
||||
// );
|
||||
//
|
||||
// List<MachineInfoDto> machineInfoDtos = page.getRecords().stream()
|
||||
// .map(machineInfo -> {
|
||||
// MachineInfoDto dto = new MachineInfoDto();
|
||||
// BeanUtils.copyProperties(machineInfo, dto);
|
||||
// // 直接调用原有枚举转换方法
|
||||
// dto.setMachineInfoType(EnumUtils.getEnumByCode(machineInfo.getMachineInfoTypeCode(), MachineInfoType.class).getMessage());
|
||||
// dto.setStatus(EnumUtils.getEnumByCode(machineInfo.getStatusCode(), MachineInfoStatus.class).getMessage());
|
||||
// dto.setAuthenticationType(EnumUtils.getEnumByCode(machineInfo.getAuthenticationTypeCode(), AuthenticationType.class).getMessage());
|
||||
// return dto;
|
||||
// })
|
||||
// .toList();
|
||||
//
|
||||
// return new PageResult<>(
|
||||
// page.getCurrent(),
|
||||
// page.getSize(),
|
||||
// page.getTotal(),
|
||||
// page.getPages(),
|
||||
// machineInfoDtos
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean updateMachineInfo(MachineInfoDto machineInfoDto) {
|
||||
// MachineInfo machineInfo = new MachineInfo();
|
||||
// BeanUtils.copyProperties(machineInfoDto, machineInfo);
|
||||
// machineInfo.setAuthenticationTypeCode(
|
||||
// "密码认证".equals(machineInfoDto.getAuthenticationType())
|
||||
// ? AuthenticationType.PASSWORD.getCode()
|
||||
// : AuthenticationType.SECRET_KEY.getCode()
|
||||
// );
|
||||
// machineInfo.setMachineInfoTypeCode(
|
||||
// "Windows".equals(machineInfoDto.getMachineInfoType())
|
||||
// ? MachineInfoType.WINDOWS.getCode()
|
||||
// : MachineInfoType.Linux.getCode()
|
||||
// );
|
||||
// return this.updateById(machineInfo);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean updateStatus(MachineInfoDto machineInfoDto) {
|
||||
// UpdateWrapper<MachineInfo> updateWrapper = new UpdateWrapper<>();
|
||||
// updateWrapper.eq("id", machineInfoDto.getId()).set("status_code", EnumUtils.getEnumByMessage(machineInfoDto.getStatus(), MachineInfoStatus.class).getCode());
|
||||
// return this.update(updateWrapper);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean bindingSecretKey(MachineInfoDto machineInfoDto) {
|
||||
// UpdateWrapper<MachineInfo> updateWrapper = new UpdateWrapper<>();
|
||||
// updateWrapper.eq("id", machineInfoDto.getId()).set("secret_key_id", machineInfoDto.getSecretKeyId()).set("authentication_type_code", 2);
|
||||
// return this.update(updateWrapper);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void deleteList(String machineInfoIds) {
|
||||
// List<Long> machineInfoIdList = Arrays.stream(machineInfoIds.split(","))
|
||||
// .map(String::trim)
|
||||
// .filter(s -> !s.isEmpty())
|
||||
// .map(Long::parseLong)
|
||||
// .collect(Collectors.toList());
|
||||
// machineInfoMapper.selectBatchIds(machineInfoIdList).forEach(machineInfo -> {
|
||||
// if (machineInfo.getStatusCode() == 1) {
|
||||
// this.removeById(machineInfo.getId());
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void deleteMachineInfo(Long machineInfoId) {
|
||||
// MachineInfo machineInfo = this.getById(machineInfoId);
|
||||
// if (machineInfo.getStatusCode() == 1) {
|
||||
// this.removeById(machineInfoId);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private QueryWrapper<MachineInfo> getMachineInfoQueryWrapper(MachineInfoDto machineInfoDto) {
|
||||
// QueryWrapper<MachineInfo> queryWrapper = new QueryWrapper<>();
|
||||
// if (machineInfoDto.getStatus() != null && !machineInfoDto.getStatus().isEmpty()) {
|
||||
// queryWrapper.eq("status_code", EnumUtils.getEnumByMessage(machineInfoDto.getStatus(), MachineInfoStatus.class).getCode());
|
||||
// }
|
||||
// if (machineInfoDto.getName() != null && !machineInfoDto.getName().isEmpty()) {
|
||||
// queryWrapper.like("name", machineInfoDto.getName());
|
||||
// }
|
||||
// if (machineInfoDto.getTag() != null && !machineInfoDto.getTag().isEmpty()) {
|
||||
// queryWrapper.like("tag", machineInfoDto.getTag());
|
||||
// }
|
||||
// if (machineInfoDto.getHostIp() != null && !machineInfoDto.getHostIp().isEmpty()) {
|
||||
// queryWrapper.like("host_ip", machineInfoDto.getHostIp());
|
||||
// }
|
||||
// if (machineInfoDto.getDescription() != null && !machineInfoDto.getDescription().isEmpty()) {
|
||||
// queryWrapper.like("description", machineInfoDto.getDescription());
|
||||
// }
|
||||
// return queryWrapper.orderByDesc("create_date");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// public boolean testConnection(Long id) {
|
||||
// //先查询机器是否存在,在判断机器可用性
|
||||
// MachineInfo machineInfo = machineInfoMapper.getById(id);
|
||||
// if (machineInfo==null){
|
||||
// throw new RuntimeException("机器不存在");
|
||||
// }
|
||||
// if (machineInfo.getStatusCode() == 0) {
|
||||
// throw new RuntimeException("机器不可用");
|
||||
// }
|
||||
// log.info("测试机器连接: {}", machineInfo.getHostIp());
|
||||
// connectionSession.setMachineInfo(machineInfo);
|
||||
// try{
|
||||
// connectionSession.connect();
|
||||
// return true;
|
||||
// } catch (Exception e) {
|
||||
// log.error("机器连接测试失败: {}", e.getMessage(), e);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public ConnectionStatus getConnectionStatus(String machineName) {
|
||||
// String sessionId = machineSessionMapping.get(machineName);
|
||||
// if (sessionId == null) {
|
||||
// return ConnectionStatus.DISCONNECTED;
|
||||
// }
|
||||
//
|
||||
// ConnectionSession session = sessions.get(sessionId);
|
||||
// return session != null ? session.getStatus() : ConnectionStatus.DISCONNECTED;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Map<String, ConnectionStatus> getAllConnectionStatus() {
|
||||
// Map<String, ConnectionStatus> result = new HashMap<>();
|
||||
//
|
||||
// machineSessionMapping.forEach((machineName, sessionId) -> {
|
||||
// ConnectionSession session = sessions.get(sessionId);
|
||||
// result.put(machineName, session != null ? session.getStatus() : ConnectionStatus.DISCONNECTED);
|
||||
// });
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String connect(MachineInfo machineInfo) {
|
||||
// if (machineInfo.getStatus().getCode() == UN_ENABLE) {
|
||||
// throw new RuntimeException("机器不可用");
|
||||
// }
|
||||
// log.info("建立机器连接: {}", machineInfo.getHostIp());
|
||||
//
|
||||
// // 检查是否已连接
|
||||
// String existingSessionId = machineSessionMapping.get(machineInfo.getName());
|
||||
// if (existingSessionId != null) {
|
||||
// ConnectionSession existingSession = sessions.get(existingSessionId);
|
||||
// if (existingSession != null && existingSession.getStatus() == ConnectionStatus.CONNECTED) {
|
||||
// log.info("机器已连接,返回现有会话: {}", machineInfo.getHostIp());
|
||||
// return existingSessionId;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// connectionSession.setMachineInfo(machineInfo);
|
||||
//
|
||||
// connectionSession.connect();
|
||||
//
|
||||
// // 生成会话ID
|
||||
// String sessionId = generateSessionId();
|
||||
//
|
||||
// // 保存会话
|
||||
// sessions.put(sessionId, connectionSession);
|
||||
// machineSessionMapping.put(machineInfo.getName(), sessionId);
|
||||
//
|
||||
// log.info("机器连接成功: {}, 会话ID: {}", machineInfo.getHostIp(), sessionId);
|
||||
// return sessionId;
|
||||
// } catch (Exception e) {
|
||||
// log.error("机器连接失败: {}", e.getMessage(), e);
|
||||
// throw new RuntimeException("机器连接失败: " + e.getMessage(), e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean disconnect(String sessionId) {
|
||||
// log.info("断开机器连接: {}", sessionId);
|
||||
//
|
||||
// ConnectionSession session = sessions.get(sessionId);
|
||||
// if (session == null) {
|
||||
// log.warn("会话不存在: {}", sessionId);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// session.disconnect();
|
||||
//
|
||||
// // 清理会话
|
||||
// sessions.remove(sessionId);
|
||||
// machineSessionMapping.entrySet().removeIf(entry -> entry.getValue().equals(sessionId));
|
||||
//
|
||||
// log.info("机器连接已断开: {}", sessionId);
|
||||
// return true;
|
||||
// } catch (Exception e) {
|
||||
// log.error("断开连接失败: {}", e.getMessage(), e);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String executeCommand(String sessionId, String command) {
|
||||
// log.info("执行命令: {}, 会话ID: {}", command, sessionId);
|
||||
//
|
||||
// ConnectionSession session = sessions.get(sessionId);
|
||||
// if (session == null) {
|
||||
// throw new RuntimeException("会话不存在: " + sessionId);
|
||||
// }
|
||||
//
|
||||
// if (session.getStatus() != ConnectionStatus.CONNECTED) {
|
||||
// throw new RuntimeException("会话未连接: " + sessionId);
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// return session.executeCommand(command);
|
||||
// } catch (Exception e) {
|
||||
// log.error("命令执行失败: {}", e.getMessage(), e);
|
||||
// throw new RuntimeException("命令执行失败: " + e.getMessage(), e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean uploadFile(String sessionId, String localFilePath, String remoteFilePath) {
|
||||
// log.info("上传文件: {} -> {}, 会话ID: {}", localFilePath, remoteFilePath, sessionId);
|
||||
//
|
||||
// ConnectionSession session = sessions.get(sessionId);
|
||||
// if (session == null) {
|
||||
// throw new RuntimeException("会话不存在: " + sessionId);
|
||||
// }
|
||||
//
|
||||
// if (session.getStatus() != ConnectionStatus.CONNECTED) {
|
||||
// throw new RuntimeException("会话未连接: " + sessionId);
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// return session.uploadFile(localFilePath, remoteFilePath);
|
||||
// } catch (Exception e) {
|
||||
// log.error("文件上传失败: {}", e.getMessage(), e);
|
||||
// throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean downloadFile(String sessionId, String remoteFilePath, String localFilePath) {
|
||||
// log.info("下载文件: {} -> {}, 会话ID: {}", remoteFilePath, localFilePath, sessionId);
|
||||
//
|
||||
// ConnectionSession session = sessions.get(sessionId);
|
||||
// if (session == null) {
|
||||
// throw new RuntimeException("会话不存在: " + sessionId);
|
||||
// }
|
||||
//
|
||||
// if (session.getStatus() != ConnectionStatus.CONNECTED) {
|
||||
// throw new RuntimeException("会话未连接: " + sessionId);
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// return session.downloadFile(remoteFilePath, localFilePath);
|
||||
// } catch (Exception e) {
|
||||
// log.error("文件下载失败: {}", e.getMessage(), e);
|
||||
// throw new RuntimeException("文件下载失败: " + e.getMessage(), e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 生成会话ID
|
||||
// */
|
||||
// private String generateSessionId() {
|
||||
// return "session-" + sessionIdGenerator.incrementAndGet();
|
||||
// }
|
||||
//}
|
@ -0,0 +1,159 @@
|
||||
//package cd.casic.module.machine.service.impl;
|
||||
//
|
||||
//import cd.casic.module.machine.controller.vo.SecretKeyDto;
|
||||
//import cd.casic.module.machine.dal.dataobject.MachineInfo;
|
||||
//import cd.casic.module.machine.dal.dataobject.SecretKey;
|
||||
//import cd.casic.module.machine.dal.mysql.SecretServiceMapper;
|
||||
//import cd.casic.module.machine.service.MachineInfoService;
|
||||
//import cn.hutool.core.io.resource.ResourceUtil;
|
||||
//import cn.hutool.core.util.IdUtil;
|
||||
//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 cd.casic.module.machine.utils.AliYunOssClient;
|
||||
//import cd.casic.module.machine.exception.ServiceException;
|
||||
////import cd.casic.module.machine.service.MachineInfoService;
|
||||
//import cd.casic.module.machine.service.SecretKeyService;
|
||||
//import jakarta.annotation.Resource;
|
||||
//import org.springframework.beans.BeanUtils;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
//@Service
|
||||
//public class SecretKeyServiceImpl extends ServiceImpl<SecretServiceMapper, SecretKey> implements SecretKeyService {
|
||||
//
|
||||
// @Resource
|
||||
// private MachineInfoService machineInfoService;
|
||||
//
|
||||
// @Resource
|
||||
// private AliYunOssClient aliYunOssClient;
|
||||
//
|
||||
// @Resource
|
||||
// private SecretServiceMapper secretServiceMapper;
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// public boolean addSecretKey(SecretKeyDto secretKeyDto){
|
||||
// if (secretKeyDto.getPath()==null)
|
||||
// {
|
||||
// throw new ServiceException(ServiceException.MACHINE_PROXY_NULL,"密钥不能为空");
|
||||
// }
|
||||
//
|
||||
// String ossPath = upLoadSecretKey(secretKeyDto.getPath());
|
||||
// if (ossPath == null){
|
||||
// throw new ServiceException(ServiceException.MACHINE_PROXY_NULL,"密钥上传失败");
|
||||
// }
|
||||
// secretKeyDto.setPath(ossPath);
|
||||
// SecretKey secretKey = new SecretKey();
|
||||
// BeanUtils.copyProperties(secretKeyDto,secretKey);
|
||||
// //todo检查密钥合法
|
||||
// return this.save(secretKey);
|
||||
//
|
||||
//
|
||||
// }
|
||||
// @Override
|
||||
// public boolean updateSecretKey(SecretKeyDto secretKeyDto) {
|
||||
//
|
||||
// Long id = secretKeyDto.getId();
|
||||
// SecretKey secretKey = this.getById(id);
|
||||
// if (secretKey == null){
|
||||
// throw new ServiceException(ServiceException.MACHINE_PROXY_NULL,"密钥不存在");
|
||||
// }
|
||||
// if (!secretKey.getPath().equals(secretKeyDto.getPath())) {
|
||||
// //todo检查密钥合法
|
||||
// String ossPath = upLoadSecretKey(secretKeyDto.getPath());
|
||||
// BeanUtils.copyProperties(secretKeyDto,secretKey);
|
||||
// secretKey.setPath(ossPath);
|
||||
// }
|
||||
// else {
|
||||
// BeanUtils.copyProperties(secretKeyDto,secretKey);
|
||||
// }
|
||||
//
|
||||
// return this.updateById(secretKey);
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void bindingMachine(Long secretKeyId, List<Long> machineIds) {
|
||||
// SecretKey secretKey = this.getById(secretKeyId);
|
||||
// if (secretKey==null){
|
||||
// throw new ServiceException(ServiceException.SECRETKEY_NULL,"密钥不存在");
|
||||
// }
|
||||
// List<MachineInfo> machineList = machineInfoService.listByIds(machineIds);
|
||||
// machineList.forEach(machine -> machine.setSecretKeyId(secretKeyId));
|
||||
// machineInfoService.updateBatchById(machineList);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// public PageResult<SecretKey> listSecretKey(SecretKeyDto secretKeyDto) {
|
||||
// QueryWrapper<SecretKey> queryWrapper = new QueryWrapper<>();
|
||||
// if (secretKeyDto.getName() != null && !secretKeyDto.getName().isEmpty()){
|
||||
// queryWrapper.like("name", secretKeyDto.getName());
|
||||
// }
|
||||
// if (secretKeyDto.getDescription() != null && !secretKeyDto.getDescription().isEmpty()){
|
||||
// queryWrapper.like("description", secretKeyDto.getDescription());
|
||||
// }
|
||||
// Page<SecretKey> page = secretServiceMapper.selectPage(new Page<>(secretKeyDto.getPageIndex(), secretKeyDto.getPageSize()), queryWrapper);
|
||||
// return new PageResult<>(
|
||||
// page.getCurrent(),
|
||||
// page.getSize(),
|
||||
// page.getTotal(),
|
||||
// page.getPages(),
|
||||
// page.getRecords()
|
||||
// );
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// public boolean deleteList(List<Long> secretKeyIds) {
|
||||
// List<SecretKey> secretKeys = this.listByIds(secretKeyIds);
|
||||
//
|
||||
// for (SecretKey secretKey : secretKeys) {
|
||||
// if (secretKey.getPath() != null && !secretKey.getPath().isEmpty()){
|
||||
// try {
|
||||
// //文件名
|
||||
// //删除子目录文件,需要在前面加上根目录文件路径
|
||||
// String fileName = secretKey.getPath().substring(secretKey.getPath().lastIndexOf("/") + 1);
|
||||
// aliYunOssClient.delete(fileName);
|
||||
// } catch (Exception e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// //todo是否删除已经绑定的机器
|
||||
// return secretServiceMapper.deleteBatchIds(secretKeyIds) > 0 ;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public String upLoadSecretKey(String localPath) {
|
||||
//
|
||||
// //使用S3FileClient上传文件
|
||||
// aliYunOssClient.init();
|
||||
//
|
||||
// //传输到指定文件,需要在path前面加上文件路径
|
||||
// String path = IdUtil.fastSimpleUUID() + ".txt";
|
||||
//
|
||||
//
|
||||
// //上传文件是从本地上传,这里传的是本地文件地址
|
||||
// byte[] content = ResourceUtil.readBytes(localPath);
|
||||
// String ossPath;
|
||||
// try {
|
||||
// ossPath = aliYunOssClient.upload(content, path, "txt");
|
||||
// }catch (Exception e) {
|
||||
// throw new RuntimeException(e+"上传文件失败");
|
||||
// }
|
||||
// return ossPath;
|
||||
// }
|
||||
//}
|
@ -0,0 +1,12 @@
|
||||
package cd.casic.module.machine.utils;
|
||||
|
||||
import cd.casic.module.infra.framework.file.core.client.s3.S3FileClient;
|
||||
import cd.casic.module.infra.framework.file.core.client.s3.S3FileClientConfig;
|
||||
|
||||
|
||||
public class AliYunOssClient extends S3FileClient{
|
||||
public AliYunOssClient(Long id, S3FileClientConfig config) {
|
||||
super(id, config);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package cd.casic.module.machine.utils;
|
||||
|
||||
|
||||
import cd.casic.module.machine.enums.CodeEnum;
|
||||
|
||||
public class EnumUtils {
|
||||
/**
|
||||
* 根据code和枚举类型获取对应的枚举值
|
||||
*
|
||||
* @param code 枚举的code值
|
||||
* @param enumClass 实现了CodeEnum接口的枚举类
|
||||
* @param <T> 枚举类型
|
||||
* @return 对应的枚举值,若未找到则返回null
|
||||
*/
|
||||
public static <T extends CodeEnum> T getEnumByCode(Object code, Class<T> enumClass) {
|
||||
if (code == null || enumClass == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 遍历枚举值查找匹配的code
|
||||
for (T enumConstant : enumClass.getEnumConstants()) {
|
||||
if (code.equals(enumConstant.getCode())) {
|
||||
return enumConstant;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据message和枚举类型获取对应的枚举值
|
||||
*
|
||||
* @param message 枚举的message值
|
||||
* @param enumClass 实现了CodeEnum接口的枚举类
|
||||
* @param <T> 枚举类型
|
||||
* @return 对应的枚举值,若未找到则返回null
|
||||
*/
|
||||
public static <T extends CodeEnum> T getEnumByMessage(String message, Class<T> enumClass) {
|
||||
if (message == null || enumClass == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 遍历枚举值查找匹配的message
|
||||
for (T enumConstant : enumClass.getEnumConstants()) {
|
||||
if (message.equals(enumConstant.getMessage())) {
|
||||
return enumConstant;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package cd.casic.module.machine.utils;
|
||||
|
||||
import io.micrometer.common.util.StringUtils;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 属性操作工具类
|
||||
*/
|
||||
public class PropertyUtils {
|
||||
|
||||
/**
|
||||
* 如果不为空则设置值
|
||||
*
|
||||
* @param value 值
|
||||
* @param setter 具体set操作
|
||||
*/
|
||||
public static void setIfNotBlank(String value, Consumer<String> setter) {
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
setter.accept(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果不为空则设置值
|
||||
*
|
||||
* @param value 值
|
||||
* @param setter 具体set操作
|
||||
*/
|
||||
public static <T> void setIfNotNull(T value, Consumer<T> setter) {
|
||||
if (value != null) {
|
||||
setter.accept(value);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for machine_env
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `machine_env`;
|
||||
CREATE TABLE `machine_env` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`create_date` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||
`update_date` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
|
||||
`machine_id` bigint NULL DEFAULT NULL,
|
||||
`env_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
|
||||
`env_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
|
||||
`sensitive` tinyint(1) NULL DEFAULT NULL COMMENT '是否敏感(0=false, 1=true, NULL=未设置)', -- 改为 tinyint 存储布尔值
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `uk_machine_env_key` (`machine_id`, `env_key`) -- 同一机器下 env_key 唯一
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for machine_info
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `machine_info`;
|
||||
CREATE TABLE `machine_info` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`create_date` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||
`update_date` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`tag` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`host_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`status_code` int NULL DEFAULT NULL COMMENT '状态编码(关联字典表)', -- 改为 int 类型
|
||||
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`ssh_port` int NULL DEFAULT NULL COMMENT 'SSH端口号(整数)', -- 改为 int 类型
|
||||
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`secret_key_id` bigint NULL DEFAULT NULL COMMENT '密钥ID(逻辑关联,无外键)',
|
||||
`machine_proxy_id` bigint NULL DEFAULT NULL COMMENT '代理ID(逻辑关联,无外键)',
|
||||
`authentication_type_code` int NULL DEFAULT NULL COMMENT '认证类型编码',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `idx_secret_key_id` (`secret_key_id`), -- 保留索引优化查询
|
||||
KEY `idx_machine_proxy_id` (`machine_proxy_id`)
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for machine_proxy
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `machine_proxy`;
|
||||
CREATE TABLE `machine_proxy` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`create_date` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||
`update_date` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
|
||||
`host_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`ssh_port` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`proxy_type_code` tinyint(1) NULL DEFAULT NULL COMMENT '代理类型编码(关联字典表)',
|
||||
`version` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`status_code` tinyint(1) NULL DEFAULT NULL COMMENT '状态编码(关联字典表)', -- 改为 tinyint(1) 类型
|
||||
`last_heartbeat_time` datetime(0) NULL DEFAULT NULL,
|
||||
`config` json NULL,
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for machine_secret_key
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `machine_secret_key`;
|
||||
CREATE TABLE `machine_secret_key` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`create_date` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||
`update_date` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
@ -0,0 +1,184 @@
|
||||
//package com.casic.machine.service.impl;
|
||||
//
|
||||
//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
//import com.casic.commons.exception.ServiceException;
|
||||
//import com.casic.commons.utils.PageResult;
|
||||
//import com.casic.machine.dto.MachineEnvDTO;
|
||||
//import com.casic.machine.entity.MachineEnv;
|
||||
//import com.casic.machine.mapper.MachineEnvMapper;
|
||||
//import com.casic.machine.service.MachineEnvService;
|
||||
//import org.junit.jupiter.api.BeforeEach;
|
||||
//import org.junit.jupiter.api.Test;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.boot.test.context.SpringBootTest;
|
||||
//import org.springframework.test.annotation.Rollback;
|
||||
//import org.springframework.test.context.jdbc.Sql;
|
||||
//import org.springframework.transaction.annotation.Transactional;
|
||||
//
|
||||
//import java.util.Date;
|
||||
//import java.util.List;
|
||||
//
|
||||
//import static org.junit.jupiter.api.Assertions.*;
|
||||
//
|
||||
//@SpringBootTest
|
||||
//@Transactional
|
||||
//@Rollback(value = true) // 测试后回滚数据
|
||||
//@Sql(scripts = {"classpath:sql/machine_env_test_data.sql"}) // 初始化测试数据(可选)
|
||||
//public class MachineEnvServiceImplTest {
|
||||
//
|
||||
// @Autowired
|
||||
// private MachineEnvService machineEnvService;
|
||||
//
|
||||
// @Autowired
|
||||
// private MachineEnvMapper machineEnvMapper;
|
||||
//
|
||||
// private MachineEnvDTO validDto;
|
||||
// private MachineEnvDTO invalidKeyDto;
|
||||
// private Long existingMachineId;
|
||||
// private Long nonExistingMachineId;
|
||||
//
|
||||
// @BeforeEach
|
||||
// public void setUp() {
|
||||
// // 准备测试数据
|
||||
// existingMachineId = 1L; // 假设数据库中存在ID为1的机器环境变量
|
||||
// nonExistingMachineId = 999L; // 不存在的机器ID
|
||||
//
|
||||
// // 有效测试数据
|
||||
// validDto = new MachineEnvDTO();
|
||||
// validDto.setMachineInfoId(existingMachineId);
|
||||
// validDto.setEnvKey("TEST_ENV_KEY");
|
||||
// validDto.setEnvValue("test-value");
|
||||
// validDto.setSensitive(true);
|
||||
//
|
||||
// // 无效Key测试数据(包含非法字符)
|
||||
// invalidKeyDto = new MachineEnvDTO();
|
||||
// invalidKeyDto.setMachineInfoId(existingMachineId);
|
||||
// invalidKeyDto.setEnvKey("test-env-key"); // 包含'-',不符合正则
|
||||
// invalidKeyDto.setEnvValue("test-value");
|
||||
// }
|
||||
//
|
||||
// // ==================== 更新环境变量测试 ====================
|
||||
// @Test
|
||||
// void testUpdateEnv_ValidData_ShouldSucceed() {
|
||||
// // 执行更新(假设数据库中已存在machineId=1的记录)
|
||||
// boolean result = machineEnvService.update(validDto);
|
||||
//
|
||||
// // 验证结果
|
||||
// assertTrue(result);
|
||||
//
|
||||
// // 检查数据库数据是否更新
|
||||
// MachineEnv updatedEnv = machineEnvMapper.selectOne(
|
||||
// new LambdaQueryWrapper<MachineEnv>().eq(MachineEnv::getMachineId, existingMachineId)
|
||||
// );
|
||||
// assertNotNull(updatedEnv);
|
||||
// assertEquals(validDto.getEnvKey(), updatedEnv.getEnvKey());
|
||||
// assertEquals(validDto.getEnvValue(), updatedEnv.getEnvValue());
|
||||
// assertEquals(validDto.getSensitive(), updatedEnv.getSensitive());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testUpdateEnv_NullDto_ShouldThrowException() {
|
||||
//
|
||||
// MachineEnvDTO machineEnvDTO = new MachineEnvDTO();
|
||||
// assertThrows(ServiceException.class, () -> {
|
||||
// machineEnvService.update(machineEnvDTO);
|
||||
// }, "环境变量不能为空");
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testUpdateEnv_InvalidKey_ShouldThrowException() {
|
||||
// assertThrows(ServiceException.class, () -> {
|
||||
// machineEnvService.update(invalidKeyDto);
|
||||
// }, "环境变量键不合法");
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testUpdateEnv_SensitiveKey_ShouldMarkAsSensitive() {
|
||||
// MachineEnvDTO sensitiveDto = new MachineEnvDTO();
|
||||
// sensitiveDto.setMachineInfoId(existingMachineId);
|
||||
// sensitiveDto.setEnvKey("DB_PASSWORD"); // 包含敏感词
|
||||
// sensitiveDto.setEnvValue("secret");
|
||||
//
|
||||
// machineEnvService.update(sensitiveDto);
|
||||
//
|
||||
// MachineEnv env = machineEnvMapper.selectOne(
|
||||
// new LambdaQueryWrapper<MachineEnv>().eq(MachineEnv::getMachineId, existingMachineId)
|
||||
// );
|
||||
// assertTrue(env.getSensitive());
|
||||
// }
|
||||
//
|
||||
// // ==================== 删除环境变量测试 ====================
|
||||
// @Test
|
||||
// void testDeleteByMachineId_ExistingId_ShouldSucceed() {
|
||||
// machineEnvService.deleteByMachineId(existingMachineId);
|
||||
// MachineEnv env = machineEnvMapper.selectById(existingMachineId);
|
||||
// assertNull(env);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testDeleteByMachineId_NonExistingId_ShouldDoNothing() {
|
||||
// machineEnvService.deleteByMachineId(nonExistingMachineId);
|
||||
// // 不抛出异常,静默处理
|
||||
// }
|
||||
//
|
||||
// // ==================== 根据机器ID查询测试 ====================
|
||||
// @Test
|
||||
// void testGetByMachineId_ExistingId_ShouldReturnDto() {
|
||||
// MachineEnvDTO dto = machineEnvService.getByMachineId(existingMachineId);
|
||||
// assertNotNull(dto);
|
||||
// assertEquals(existingMachineId, dto.getMachineInfoId());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testGetByMachineId_NonExistingId_ShouldReturnNull() {
|
||||
// MachineEnvDTO dto = machineEnvService.getByMachineId(nonExistingMachineId);
|
||||
// assertNull(dto);
|
||||
// }
|
||||
//
|
||||
// // ==================== 列表查询测试 ====================
|
||||
// @Test
|
||||
// void testListEnv_Pagination_ShouldReturnValidPage() {
|
||||
// MachineEnvDTO queryDto = new MachineEnvDTO();
|
||||
// queryDto.setPageIndex(1);
|
||||
// queryDto.setPageSize(10);
|
||||
// queryDto.setEnvKey("TEST"); // 假设测试数据中存在包含"TEST"的键
|
||||
//
|
||||
// PageResult<MachineEnvDTO> pageResult = machineEnvService.listEnv(queryDto);
|
||||
//
|
||||
// assertNotNull(pageResult.getList());
|
||||
// assertTrue(pageResult.getTotal() >= 0);
|
||||
// assertEquals(1, pageResult.getPageNum());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testListEnv_SortByCreateTime_ShouldBeOrdered() {
|
||||
// MachineEnvDTO queryDto = new MachineEnvDTO();
|
||||
// queryDto.setSortField("createTime");
|
||||
// queryDto.setSortDirection("desc");
|
||||
//
|
||||
// PageResult<MachineEnvDTO> pageResult = machineEnvService.listEnv(queryDto);
|
||||
//
|
||||
// List<MachineEnvDTO> list = pageResult.getList();
|
||||
// if (!list.isEmpty()) {
|
||||
// Date prevDate = list.get(0).getCreateDate();
|
||||
// for (int i = 1; i < list.size(); i++) {
|
||||
// Date currDate = list.get(i).getCreateDate();
|
||||
// assertTrue(currDate.before(prevDate) || currDate.equals(prevDate), "排序应为降序");
|
||||
// prevDate = currDate;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // ==================== 批量删除测试 ====================
|
||||
// @Test
|
||||
// void testDeleteList_ValidIds_ShouldDeleteBatch() {
|
||||
// // 假设测试数据中有ID为1和2的记录
|
||||
// List<Long> ids = List.of(1L, 2L);
|
||||
// machineEnvService.deleteList(ids);
|
||||
//
|
||||
// long count = machineEnvMapper.selectCount(new LambdaQueryWrapper<MachineEnv>().in(MachineEnv::getId, ids));
|
||||
// assertEquals(0, count);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
@ -0,0 +1,222 @@
|
||||
//package com.casic.machine.service.impl;
|
||||
//
|
||||
//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
//import com.casic.commons.exception.ServiceException;
|
||||
//import com.casic.commons.utils.EnumUtils;
|
||||
//import com.casic.commons.utils.PageResult;
|
||||
//import com.casic.machine.dto.MachineProxyDTO;
|
||||
//import com.casic.machine.entity.MachineProxy;
|
||||
//import com.casic.machine.enums.MachineProxyStatus;
|
||||
//import com.casic.machine.enums.MachineProxyType;
|
||||
//import com.casic.machine.mapper.MachineProxyMapper;
|
||||
//import com.casic.machine.service.MachineProxyService;
|
||||
//import org.junit.jupiter.api.BeforeEach;
|
||||
//import org.junit.jupiter.api.Test;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.boot.test.context.SpringBootTest;
|
||||
//import org.springframework.test.annotation.Rollback;
|
||||
//import org.springframework.test.context.jdbc.Sql;
|
||||
//import org.springframework.transaction.annotation.Transactional;
|
||||
//
|
||||
//import java.util.*;
|
||||
//
|
||||
//import static org.junit.jupiter.api.Assertions.*;
|
||||
//
|
||||
//@SpringBootTest
|
||||
//@Transactional
|
||||
//@Rollback(true)
|
||||
//@Sql(scripts = {"classpath:sql/machine_proxy_test_data.sql"})
|
||||
//public class MachineProxyServiceImplTest {
|
||||
//
|
||||
// @Autowired
|
||||
// private MachineProxyService machineProxyService;
|
||||
//
|
||||
// @Autowired
|
||||
// private MachineProxyMapper machineProxyMapper;
|
||||
//
|
||||
// private MachineProxyDTO validProxyDTO;
|
||||
// private Long existingProxyId;
|
||||
// private Long nonExistingProxyId;
|
||||
//
|
||||
// @BeforeEach
|
||||
// public void setUp() {
|
||||
// // 初始化测试数据(假设 SQL 脚本已插入一条状态为 OFFLINE 的代理)
|
||||
// existingProxyId = 1L;
|
||||
// nonExistingProxyId = 999L;
|
||||
//
|
||||
// // 有效代理 DTO
|
||||
// validProxyDTO = new MachineProxyDTO();
|
||||
// validProxyDTO.setProxyType(MachineProxyType.SOCKS5.getMessage());
|
||||
// validProxyDTO.setHostIp("192.168.1.100");
|
||||
// validProxyDTO.setSshPort("22");
|
||||
// validProxyDTO.setUsername("test_user");
|
||||
// validProxyDTO.setStatus(MachineProxyStatus.ONLINE.getMessage());
|
||||
// }
|
||||
//
|
||||
// // ============================== 注册代理测试 ==============================
|
||||
// @Test
|
||||
// void testRegister_ValidData_ShouldSucceed() {
|
||||
// // 执行注册
|
||||
// boolean result = machineProxyService.register(validProxyDTO);
|
||||
// assertTrue(result, "注册失败");
|
||||
//
|
||||
// // 使用 Lambda 表达式查询(推荐)
|
||||
// MachineProxy proxy = machineProxyMapper.selectOne(
|
||||
// new LambdaQueryWrapper<MachineProxy>()
|
||||
// .eq(MachineProxy::getHostIp, validProxyDTO.getHostIp())
|
||||
// );
|
||||
//
|
||||
// // 断言数据存在
|
||||
// assertNotNull(proxy, "代理记录未写入数据库");
|
||||
// assertEquals(MachineProxyType.SOCKS5.getCode(), proxy.getProxyTypeCode());
|
||||
// assertEquals(MachineProxyStatus.INSTALLING.getCode(), proxy.getStatusCode());
|
||||
// assertEquals(validProxyDTO.getHostIp(), proxy.getHostIp(), "IP 地址不一致");
|
||||
// }
|
||||
//
|
||||
// // ============================== 更新状态测试 ==============================
|
||||
// @Test
|
||||
// void testUpdateStatus_ExistingProxy_ShouldUpdateStatus() {
|
||||
// // 准备数据:查询现有代理(状态为 OFFLINE)
|
||||
// MachineProxy proxy = machineProxyMapper.selectById(existingProxyId);
|
||||
// assertEquals(MachineProxyStatus.OFFLINE.getCode(), proxy.getStatusCode());
|
||||
//
|
||||
// // 执行状态更新为 ONLINE
|
||||
// validProxyDTO.setId(existingProxyId);
|
||||
// validProxyDTO.setStatus(MachineProxyStatus.ONLINE.getMessage());
|
||||
// boolean result = machineProxyService.updateStatus(validProxyDTO);
|
||||
//
|
||||
// // 验证结果
|
||||
// assertTrue(result);
|
||||
// proxy = machineProxyMapper.selectById(existingProxyId);
|
||||
// assertEquals(MachineProxyStatus.ONLINE.getCode(), proxy.getStatusCode());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testUpdateStatus_NullDto_ShouldThrowException() {
|
||||
// assertThrows(ServiceException.class, () -> {
|
||||
// machineProxyService.updateStatus(null);
|
||||
// }, "MachineProxyDTO对象为空");
|
||||
// }
|
||||
//
|
||||
// // ============================== 心跳测试 ==============================
|
||||
// @Test
|
||||
// void testHeartbeat_ValidData_ShouldUpdateVersionAndStatus() {
|
||||
// // 准备数据:现有代理状态为 OFFLINE,版本为 1.0.0
|
||||
// MachineProxy proxy = machineProxyMapper.selectById(existingProxyId);
|
||||
// assertEquals("1.0.0", proxy.getVersion());
|
||||
// assertEquals(MachineProxyStatus.OFFLINE.getCode(), proxy.getStatusCode());
|
||||
//
|
||||
// // 发送心跳,更新版本和状态
|
||||
// validProxyDTO.setId(existingProxyId);
|
||||
// validProxyDTO.setVersion("2.0.0");
|
||||
// validProxyDTO.setStatus(MachineProxyStatus.ONLINE.getMessage());
|
||||
// machineProxyService.heartbeat(validProxyDTO);
|
||||
//
|
||||
// // 验证结果
|
||||
// proxy = machineProxyMapper.selectById(existingProxyId);
|
||||
// assertEquals("2.0.0", proxy.getVersion());
|
||||
// assertEquals(MachineProxyStatus.ONLINE.getCode(), proxy.getStatusCode());
|
||||
// }
|
||||
//
|
||||
// // ============================== 状态统计测试 ==============================
|
||||
// @Test
|
||||
// void testGetStatusStatistics_ShouldReturnValidCounts() {
|
||||
// // 假设测试数据中有 OFFLINE(1)、INSTALLING(1)、ONLINE(1) 三种状态
|
||||
// Map<String, Long> stats = machineProxyService.getStatusStatistics();
|
||||
//
|
||||
// // 验证统计结果
|
||||
// assertEquals(3, stats.size());
|
||||
// assertTrue(stats.containsKey(MachineProxyStatus.OFFLINE.getMessage()));
|
||||
// assertTrue(stats.containsKey(MachineProxyStatus.INSTALLING.getMessage()));
|
||||
// assertTrue(stats.containsKey(MachineProxyStatus.ONLINE.getMessage()));
|
||||
// assertEquals(1L, stats.get(MachineProxyStatus.OFFLINE.getMessage()));
|
||||
// }
|
||||
//
|
||||
// // ============================== 更新配置测试 ==============================
|
||||
// @Test
|
||||
// void testUpdateConfig_ValidConfig_ShouldSucceed() {
|
||||
// // 准备数据:现有代理配置为空
|
||||
// MachineProxy proxy = machineProxyMapper.selectById(existingProxyId);
|
||||
// assertNull(proxy.getConfig());
|
||||
//
|
||||
// // 更新配置
|
||||
// validProxyDTO.setId(existingProxyId);
|
||||
// validProxyDTO.setConfig("{\"port\": 8080}");
|
||||
// boolean result = machineProxyService.updateConfig(validProxyDTO);
|
||||
//
|
||||
// // 验证结果
|
||||
// assertTrue(result);
|
||||
// proxy = machineProxyMapper.selectById(existingProxyId);
|
||||
// assertEquals("{\"port\": 8080}", proxy.getConfig());
|
||||
// }
|
||||
//
|
||||
// // ============================== 删除代理测试 ==============================
|
||||
// @Test
|
||||
// void testDelete_OfflineProxy_ShouldDeleteSuccessfully() {
|
||||
// // 准备数据:状态为 OFFLINE 的代理 ID
|
||||
// List<Long> ids = Collections.singletonList(existingProxyId);
|
||||
// machineProxyService.delete(ids);
|
||||
//
|
||||
// // 验证删除
|
||||
// MachineProxy proxy = machineProxyMapper.selectById(existingProxyId);
|
||||
// assertNull(proxy);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testDelete_OnlineProxy_ShouldThrowException() {
|
||||
// // 先将代理状态改为 ONLINE
|
||||
// MachineProxy onlineProxy = new MachineProxy();
|
||||
// onlineProxy.setId(existingProxyId);
|
||||
// onlineProxy.setStatusCode(MachineProxyStatus.ONLINE.getCode());
|
||||
// machineProxyMapper.updateById(onlineProxy);
|
||||
//
|
||||
// // 执行删除
|
||||
// List<Long> ids = Collections.singletonList(existingProxyId);
|
||||
// assertThrows(IllegalArgumentException.class, () -> {
|
||||
// machineProxyService.delete(ids);
|
||||
// }, "以下代理处于在线状态,无法删除: 1");
|
||||
// }
|
||||
//
|
||||
// // ============================== 列表查询测试 ==============================
|
||||
// @Test
|
||||
// void testList_WithStatusFilter_ShouldReturnMatchedRecords() {
|
||||
// // 查询状态为 OFFLINE 的代理
|
||||
// MachineProxyDTO queryDto = new MachineProxyDTO();
|
||||
// queryDto.setStatus(MachineProxyStatus.OFFLINE.getMessage());
|
||||
//
|
||||
// PageResult<MachineProxyDTO> pageResult = machineProxyService.list(queryDto);
|
||||
//
|
||||
// // 验证结果
|
||||
// assertFalse(pageResult.getList().isEmpty());
|
||||
// pageResult.getList().forEach(dto ->
|
||||
// assertEquals(MachineProxyStatus.OFFLINE.getMessage(), dto.getStatus())
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testList_WithHostIpFilter_ShouldReturnMatchedRecords() {
|
||||
// // 假设测试数据中存在 host_ip 为 "192.168.1.1" 的代理
|
||||
// MachineProxyDTO queryDto = new MachineProxyDTO();
|
||||
// queryDto.setHostIp("192.168.1.1");
|
||||
//
|
||||
// PageResult<MachineProxyDTO> pageResult = machineProxyService.list(queryDto);
|
||||
//
|
||||
// // 验证结果
|
||||
// assertFalse(pageResult.getList().isEmpty());
|
||||
// pageResult.getList().forEach(dto ->
|
||||
// assertEquals("192.168.1.1", dto.getHostIp())
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// // ============================== 辅助方法测试 ==============================
|
||||
// @Test
|
||||
// void testEnumUtils_ConvertCodeToMessage() {
|
||||
// // 验证代理类型枚举转换
|
||||
// String typeMessage = EnumUtils.getEnumByCode(MachineProxyType.HTTP.getCode(), MachineProxyType.class).getMessage();
|
||||
// assertEquals("HTTP", typeMessage);
|
||||
//
|
||||
// // 验证状态枚举转换
|
||||
// String statusMessage = EnumUtils.getEnumByCode(MachineProxyStatus.INSTALLING.getCode(), MachineProxyStatus.class).getMessage();
|
||||
// assertEquals("安装中", statusMessage);
|
||||
// }
|
||||
//}
|
@ -0,0 +1,176 @@
|
||||
//package com.casic.machine.service.impl;
|
||||
//
|
||||
//import com.casic.commons.exception.ServiceException;
|
||||
//import com.casic.machine.dto.MachineInfoDto;
|
||||
//import com.casic.machine.entity.MachineInfo;
|
||||
//import com.casic.machine.enums.AuthenticationType;
|
||||
//import com.casic.machine.enums.ConnectionStatus;
|
||||
//import com.casic.machine.enums.MachineInfoStatus;
|
||||
//import org.junit.jupiter.api.BeforeEach;
|
||||
//import org.junit.jupiter.api.Test;
|
||||
//import org.springframework.beans.BeanUtils;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.boot.test.context.SpringBootTest;
|
||||
//import org.springframework.test.annotation.Rollback;
|
||||
//import org.springframework.test.context.jdbc.Sql;
|
||||
//import org.springframework.transaction.annotation.Transactional;
|
||||
//
|
||||
//import java.util.Collections;
|
||||
//
|
||||
//import static org.junit.jupiter.api.Assertions.*;
|
||||
//
|
||||
//@SpringBootTest
|
||||
//@Transactional
|
||||
//@Rollback(true)
|
||||
//@Sql(scripts = {"classpath:sql/machine_info_test_data.sql"})
|
||||
//public class MachineinfoServiceImplTest {
|
||||
//
|
||||
// @Autowired
|
||||
// private MachineinfoServiceImpl machineInfoService;
|
||||
//
|
||||
// private MachineInfoDto validMachineInfoDto;
|
||||
// private Long existingMachineId;
|
||||
// private Long nonExistingMachineId;
|
||||
//
|
||||
// @BeforeEach
|
||||
// public void setUp() {
|
||||
// // 初始化测试数据(假设 SQL 脚本已插入一条状态为 ENABLE 的机器)
|
||||
// existingMachineId = 1L;
|
||||
// nonExistingMachineId = 999L;
|
||||
//
|
||||
// // 有效机器信息 DTO
|
||||
// validMachineInfoDto = new MachineInfoDto();
|
||||
// validMachineInfoDto.setName("Test Machine");
|
||||
// validMachineInfoDto.setHostIp("192.168.1.101");
|
||||
// validMachineInfoDto.setSshPort("22");
|
||||
// validMachineInfoDto.setUsername("testuser");
|
||||
// validMachineInfoDto.setAuthenticationType(AuthenticationType.PASSWORD.getMessage());
|
||||
// validMachineInfoDto.setStatus(MachineInfoStatus.ENABLE.getMessage());
|
||||
// }
|
||||
//
|
||||
// // ======================= 新增机器测试 =======================
|
||||
// @Test
|
||||
// void testAddMachineInfo_ValidData_ShouldSucceed() {
|
||||
// boolean result = machineInfoService.addMachineInfo(validMachineInfoDto);
|
||||
// assertTrue(result);
|
||||
//
|
||||
// // 验证数据库存在记录
|
||||
// MachineInfo machineInfo = machineInfoService.getById(validMachineInfoDto.getId());
|
||||
// assertNotNull(machineInfo);
|
||||
// assertEquals(validMachineInfoDto.getHostIp(), machineInfo.getHostIp());
|
||||
// assertEquals(AuthenticationType.PASSWORD.getCode(), machineInfo.getAuthenticationTypeCode());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testAddMachineInfo_NullDto_ShouldThrowException() {
|
||||
// assertThrows(ServiceException.class, () -> {
|
||||
// machineInfoService.addMachineInfo(null);
|
||||
// }, "机器信息为空");
|
||||
// }
|
||||
//
|
||||
// // ======================= 列表查询测试 =======================
|
||||
// @Test
|
||||
// void testListMachineInfo_WithStatusFilter_ShouldReturnValidRecords() {
|
||||
// MachineInfoDto queryDto = new MachineInfoDto();
|
||||
// queryDto.setStatus(MachineInfoStatus.ENABLE.getMessage());
|
||||
//
|
||||
// var pageResult = machineInfoService.listMachineInfo(queryDto);
|
||||
// assertFalse(pageResult.getList().isEmpty());
|
||||
// pageResult.getList().forEach(dto ->
|
||||
// assertEquals(MachineInfoStatus.ENABLE.getMessage(), dto.getStatus())
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testListMachineInfo_WithHostIpFilter_ShouldFilterRecords() {
|
||||
// MachineInfoDto queryDto = new MachineInfoDto();
|
||||
// queryDto.setHostIp("192.168.1.100"); // 假设测试数据中的 IP
|
||||
//
|
||||
// var pageResult = machineInfoService.listMachineInfo(queryDto);
|
||||
// assertFalse(pageResult.getList().isEmpty());
|
||||
// pageResult.getList().forEach(dto ->
|
||||
// assertTrue(dto.getHostIp().contains("192.168.1.100"))
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// // ======================= 更新机器状态测试 =======================
|
||||
// @Test
|
||||
// void testUpdateStatus_ValidId_ShouldUpdateStatus() {
|
||||
// boolean result = machineInfoService.updateStatus(existingMachineId, MachineInfoStatus.UN_ENABLE.getMessage());
|
||||
// assertTrue(result);
|
||||
//
|
||||
// MachineInfo machineInfo = machineInfoService.getById(existingMachineId);
|
||||
// assertEquals(MachineInfoStatus.UN_ENABLE.getCode(), machineInfo.getStatus());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testUpdateStatus_NonExistingId_ShouldFail() {
|
||||
// boolean result = machineInfoService.updateStatus(nonExistingMachineId, MachineInfoStatus.UN_ENABLE.getMessage());
|
||||
// assertFalse(result);
|
||||
// }
|
||||
//
|
||||
// // ======================= 连接测试 =======================
|
||||
// @Test
|
||||
// void testTestConnection_EnabledMachine_ShouldSucceed() {
|
||||
// MachineInfo machineInfo = machineInfoService.getById(existingMachineId);
|
||||
// assertTrue(machineInfoService.testConnection(machineInfo));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testTestConnection_DisabledMachine_ShouldThrowException() {
|
||||
// // 先禁用机器
|
||||
// machineInfoService.updateStatus(existingMachineId, MachineInfoStatus.UN_ENABLE.getMessage());
|
||||
// MachineInfo disabledMachine = machineInfoService.getById(existingMachineId);
|
||||
//
|
||||
// assertThrows(RuntimeException.class, () -> {
|
||||
// machineInfoService.testConnection(disabledMachine);
|
||||
// }, "机器不可用");
|
||||
// }
|
||||
//
|
||||
// // ======================= 会话管理测试 =======================
|
||||
// @Test
|
||||
// void testConnect_NewMachine_ShouldCreateSession() {
|
||||
// MachineInfo machineInfo = machineInfoService.getById(existingMachineId);
|
||||
// String sessionId = machineInfoService.connect(machineInfo);
|
||||
//
|
||||
// assertNotNull(sessionId);
|
||||
// assertTrue(sessionId.startsWith("session-"));
|
||||
// assertEquals(ConnectionStatus.CONNECTING, machineInfoService.getConnectionStatus(machineInfo.getName()));
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// // ======================= 删除机器测试 =======================
|
||||
// @Test
|
||||
// void testDeleteMachineInfo_EnabledMachine_ShouldDelete() {
|
||||
// machineInfoService.deleteMachineInfo(existingMachineId);
|
||||
// assertNull(machineInfoService.getById(existingMachineId));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testDeleteList_ValidIds_ShouldDeleteBatch() {
|
||||
// machineInfoService.deleteList(Collections.singletonList(existingMachineId));
|
||||
// var list = machineInfoService.list();
|
||||
// assertFalse(list.contains(existingMachineId));
|
||||
// }
|
||||
//
|
||||
// // ======================= 辅助功能测试 =======================
|
||||
// @Test
|
||||
// void testAuthenticationTypeConversion() {
|
||||
// validMachineInfoDto.setAuthenticationType(AuthenticationType.SECRET_KEY.getMessage());
|
||||
// MachineInfo machineInfo = new MachineInfo();
|
||||
// BeanUtils.copyProperties(validMachineInfoDto, machineInfo);
|
||||
//
|
||||
// assertEquals(AuthenticationType.SECRET_KEY.getCode(), machineInfo.getAuthenticationTypeCode());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testGetAllConnectionStatus_ShouldReturnStatusMap() {
|
||||
// MachineInfo machineInfo = machineInfoService.getById(existingMachineId);
|
||||
// machineInfoService.connect(machineInfo);
|
||||
//
|
||||
// var statusMap = machineInfoService.getAllConnectionStatus();
|
||||
// assertFalse(statusMap.isEmpty());
|
||||
// assertTrue(statusMap.containsValue(ConnectionStatus.CONNECTING));
|
||||
// }
|
||||
//}
|
@ -0,0 +1,218 @@
|
||||
//package com.casic.machine.service.impl;
|
||||
//
|
||||
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
//import com.casic.commons.exception.ServiceException;
|
||||
//import com.casic.commons.utils.AliOssUtil;
|
||||
//import com.casic.machine.entity.MachineInfo;
|
||||
//import com.casic.machine.entity.SecretKey;
|
||||
//import com.casic.machine.dto.SecretKeyDto;
|
||||
//import com.casic.machine.mapper.SecretServiceMapper;
|
||||
//import com.casic.machine.service.MachineInfoService;
|
||||
//import com.jayway.jsonpath.internal.Utils;
|
||||
//import org.junit.jupiter.api.BeforeEach;
|
||||
//import org.junit.jupiter.api.Test;
|
||||
//import org.mockito.InjectMocks;
|
||||
//import org.mockito.Mock;
|
||||
//import org.mockito.MockitoAnnotations;
|
||||
//import org.springframework.beans.BeanUtils;
|
||||
//import org.springframework.core.io.InputStreamResource;
|
||||
//import org.springframework.http.ResponseEntity;
|
||||
//import org.springframework.mock.web.MockMultipartFile;
|
||||
//import org.springframework.test.util.ReflectionTestUtils;
|
||||
//
|
||||
//import java.io.ByteArrayInputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.util.Collections;
|
||||
//import java.util.List;
|
||||
//
|
||||
//import static org.junit.jupiter.api.Assertions.*;
|
||||
//import static org.mockito.ArgumentMatchers.any;
|
||||
//import static org.mockito.Mockito.*;
|
||||
//
|
||||
//@SuppressWarnings("unchecked")
|
||||
//public class SecretKeyServiceImplTest {
|
||||
//
|
||||
// @InjectMocks
|
||||
// private SecretKeyServiceImpl secretKeyService;
|
||||
//
|
||||
// @Mock
|
||||
// private AliOssUtil aliOssUtil;
|
||||
//
|
||||
// @Mock
|
||||
// private SecretServiceMapper secretServiceMapper;
|
||||
//
|
||||
// @Mock
|
||||
// private MachineInfoService machineInfoService;
|
||||
//
|
||||
// private SecretKeyDto validSecretKeyDto;
|
||||
// private MockMultipartFile mockFile;
|
||||
// private final Long TEST_SECRET_KEY_ID = 1L;
|
||||
// private final String TEST_FILE_NAME = "test_key.pem";
|
||||
// private final String TEST_PATH = "https://bucket.endpoint/test_key.pem";
|
||||
//
|
||||
// @BeforeEach
|
||||
// public void setUp() throws IOException {
|
||||
// MockitoAnnotations.openMocks(this);
|
||||
// validSecretKeyDto = new SecretKeyDto();
|
||||
// validSecretKeyDto.setName("Test Key");
|
||||
// validSecretKeyDto.setDescription("Test secret key");
|
||||
//
|
||||
// // 创建模拟文件
|
||||
// byte[] fileContent = "test content".getBytes();
|
||||
// mockFile = new MockMultipartFile(
|
||||
// "file",
|
||||
// TEST_FILE_NAME,
|
||||
// "application/octet-stream",
|
||||
// new ByteArrayInputStream(fileContent)
|
||||
// );
|
||||
//
|
||||
// // 模拟 OSS 工具返回值
|
||||
// when(aliOssUtil.save(any(MockMultipartFile.class))).thenReturn(TEST_FILE_NAME);
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // ======================= 新增密钥测试 =======================
|
||||
// @Test
|
||||
// void testAddSecretKey_ValidData_ShouldSucceed() throws IOException {
|
||||
// // 执行新增
|
||||
// boolean result = secretKeyService.addSecretKey(validSecretKeyDto, mockFile);
|
||||
//
|
||||
// // 验证 OSS 保存调用
|
||||
// verify(aliOssUtil, times(1)).save(mockFile);
|
||||
//
|
||||
// // 验证实体属性
|
||||
// SecretKey savedKey = new SecretKey();
|
||||
// BeanUtils.copyProperties(validSecretKeyDto, savedKey);
|
||||
// savedKey.setFileName(TEST_FILE_NAME);
|
||||
// savedKey.setPath(TEST_PATH);
|
||||
//
|
||||
// // 验证 Mapper 调用
|
||||
// verify(secretServiceMapper, times(1)).insert(savedKey);
|
||||
// assertTrue(result);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testAddSecretKey_NullFile_ShouldThrowException() {
|
||||
// assertThrows(ServiceException.class, () -> {
|
||||
// secretKeyService.addSecretKey(validSecretKeyDto, null);
|
||||
// }, "文件为空");
|
||||
// }
|
||||
//
|
||||
// // ======================= 绑定机器测试 =======================
|
||||
// @Test
|
||||
// void testBindingMachine_ValidIds_ShouldUpdateMachine() {
|
||||
// // 模拟机器列表
|
||||
// List<Long> machineIds = Collections.singletonList(1L);
|
||||
// when(machineInfoService.listByIds(machineIds)).thenReturn(Collections.singletonList(new MachineInfo()));
|
||||
//
|
||||
// secretKeyService.bindingMachine(TEST_SECRET_KEY_ID, machineIds);
|
||||
//
|
||||
// // 验证机器信息更新
|
||||
// verify(machineInfoService, times(1)).listByIds(machineIds);
|
||||
// machineIds.forEach(id -> {
|
||||
// verify(machineInfoService, times(1)).update(any());
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// // ======================= 更新密钥测试 =======================
|
||||
// @Test
|
||||
// void testUpdateSecretKey_WithNewFile_ShouldUpdatePath() throws IOException {
|
||||
// MockMultipartFile newFile = new MockMultipartFile(
|
||||
// "file",
|
||||
// "new_key.pem",
|
||||
// "application/octet-stream",
|
||||
// new ByteArrayInputStream("new content".getBytes())
|
||||
// );
|
||||
// when(aliOssUtil.save(newFile)).thenReturn("new_key.pem");
|
||||
//
|
||||
// validSecretKeyDto.setId(TEST_SECRET_KEY_ID);
|
||||
// boolean result = secretKeyService.updateSecretKey(validSecretKeyDto, newFile);
|
||||
//
|
||||
// // 验证 OSS 调用和路径更新
|
||||
// verify(aliOssUtil, times(1)).save(newFile);
|
||||
// SecretKey updatedKey = new SecretKey();
|
||||
// BeanUtils.copyProperties(validSecretKeyDto, updatedKey);
|
||||
// updatedKey.setFileName("new_key.pem");
|
||||
// updatedKey.setPath("https://bucket.endpoint/new_key.pem");
|
||||
// verify(secretServiceMapper, times(1)).updateById(updatedKey);
|
||||
// assertTrue(result);
|
||||
// }
|
||||
//
|
||||
// // ======================= 删除密钥测试 =======================
|
||||
// @Test
|
||||
// void testDeleteSecretKey_ValidId_ShouldDeleteFileAndRecord() {
|
||||
// SecretKey secretKey = new SecretKey();
|
||||
// secretKey.setId(TEST_SECRET_KEY_ID);
|
||||
// secretKey.setFileName(TEST_FILE_NAME);
|
||||
// when(secretServiceMapper.selectById(TEST_SECRET_KEY_ID)).thenReturn(secretKey);
|
||||
//
|
||||
// boolean result = secretKeyService.deleteSecretKey(TEST_SECRET_KEY_ID);
|
||||
//
|
||||
// // 验证 OSS 删除和 Mapper 调用
|
||||
// verify(aliOssUtil, times(1)).deleteFile(TEST_FILE_NAME);
|
||||
// verify(secretServiceMapper, times(1)).deleteById(TEST_SECRET_KEY_ID);
|
||||
// assertTrue(result);
|
||||
// }
|
||||
//
|
||||
// // ======================= 列表查询测试 =======================
|
||||
// @Test
|
||||
// void testListSecretKey_WithNameFilter_ShouldReturnMatchedRecords() {
|
||||
// SecretKeyDto queryDto = new SecretKeyDto();
|
||||
// queryDto.setName("Test");
|
||||
// QueryWrapper<SecretKey> wrapper = new QueryWrapper<>();
|
||||
// wrapper.like("name", "Test");
|
||||
//
|
||||
// when(secretServiceMapper.selectPage(any(), any())).thenReturn(new Page<>());
|
||||
//
|
||||
// secretKeyService.listSecretKey(queryDto);
|
||||
// verify(secretServiceMapper, times(1)).selectPage(any(), wrapper);
|
||||
// }
|
||||
//
|
||||
// // ======================= 文件下载测试 =======================
|
||||
// @Test
|
||||
// void testDownloadSecretKeyFile_ValidId_ShouldReturnResponseEntity() throws IOException {
|
||||
// SecretKey secretKey = new SecretKey();
|
||||
// secretKey.setFileName(TEST_FILE_NAME);
|
||||
// when(secretServiceMapper.selectById(TEST_SECRET_KEY_ID)).thenReturn(secretKey);
|
||||
// InputStreamResource inputStreamResource = new InputStreamResource(
|
||||
// new ByteArrayInputStream("test content".getBytes())
|
||||
// );
|
||||
// when(aliOssUtil.downloadFile(TEST_FILE_NAME)).thenReturn(
|
||||
// ResponseEntity.ok(inputStreamResource)
|
||||
// );
|
||||
//
|
||||
// ResponseEntity<InputStreamResource> response = secretKeyService.downloadSecretKeyFile(TEST_SECRET_KEY_ID);
|
||||
// assertNotNull(response);
|
||||
// assertEquals("test content", Utils.toString(response.getBody().getInputStream()));
|
||||
// }
|
||||
//
|
||||
// // ======================= 批量删除测试 =======================
|
||||
// @Test
|
||||
// void testDeleteList_ValidIds_ShouldSubmitAsyncDelete() {
|
||||
// List<Long> ids = Collections.singletonList(TEST_SECRET_KEY_ID);
|
||||
// SecretKey secretKey = new SecretKey();
|
||||
// secretKey.setFileName(TEST_FILE_NAME);
|
||||
// when(secretServiceMapper.selectBatchIds(ids)).thenReturn(Collections.singletonList(secretKey));
|
||||
//
|
||||
// secretKeyService.deleteList(ids);
|
||||
//
|
||||
// // 验证异步任务提交
|
||||
// verify(secretKeyService.FILE_DELETE_EXECUTOR, times(1)).execute(any(Runnable.class));
|
||||
// verify(secretServiceMapper, times(1)).deleteBatchIds(ids);
|
||||
// }
|
||||
//
|
||||
// // ======================= 异常处理测试 =======================
|
||||
// @Test
|
||||
// void testDeleteSecretKey_FileDeleteFailed_ShouldThrowException() {
|
||||
// aliOssUtil.deleteFile(TEST_FILE_NAME);
|
||||
// SecretKey secretKey = new SecretKey();
|
||||
// secretKey.setId(TEST_SECRET_KEY_ID);
|
||||
// secretKey.setFileName(TEST_FILE_NAME);
|
||||
// when(secretServiceMapper.selectById(TEST_SECRET_KEY_ID)).thenReturn(secretKey);
|
||||
//
|
||||
// assertThrows(ServiceException.class, () -> {
|
||||
// secretKeyService.deleteSecretKey(TEST_SECRET_KEY_ID);
|
||||
// }, "删除文件失败");
|
||||
// }
|
||||
//}
|
@ -14,6 +14,7 @@
|
||||
<module>module-infra-biz</module>
|
||||
<module>module-system-api</module>
|
||||
<module>module-system-biz</module>
|
||||
<module>module-ci-machine</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>modules</artifactId>
|
||||
|
@ -25,6 +25,11 @@
|
||||
<artifactId>module-system-biz</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cd.casic.boot</groupId>
|
||||
<artifactId>module-ci-machine</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cd.casic.boot</groupId>
|
||||
|
@ -156,3 +156,12 @@ logging:
|
||||
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # 禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
|
||||
|
||||
debug: false
|
||||
|
||||
|
||||
#阿里云oss
|
||||
aliyun:
|
||||
oss:
|
||||
endpoint: https://oss-cn-beijing.aliyuncs.com
|
||||
accessKeyId: LTAI5tPCKES4ZxdRKybGjJf4
|
||||
accessKeySecret: mtX94qmxnWR2FDem0z38qjv0rrILSE
|
||||
bucketName: kkt-web-tlias
|
||||
|
Loading…
x
Reference in New Issue
Block a user