Merge remote-tracking branch 'origin/jenkins-engin' into jenkins-engin

# Conflicts:
#	modules/module-ci-machine/src/main/java/cd/casic/module/machine/controller/SecretKeyController.java
#	modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/SecretKeyService.java
#	modules/module-ci-machine/src/main/java/cd/casic/module/machine/service/impl/SecretKeyServiceImpl.java
#	modules/module-ci-machine/src/main/java/cd/casic/module/machine/utils/AliOssUtil.java
This commit is contained in:
唐潇凯 2025-06-04 14:45:15 +08:00
commit 4815b590c4
24 changed files with 227 additions and 337 deletions

View File

@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
import static cd.casic.framework.commons.pojo.CommonResult.success; import static cd.casic.framework.commons.pojo.CommonResult.success;
@ -44,29 +45,27 @@ public class MachineEnvController {
@DeleteMapping("/delete") @DeleteMapping("/delete")
@Operation(summary = "删除机器的环境变量") @Operation(summary = "删除机器的环境变量")
public CommonResult deleteByMachineId( public CommonResult deleteByMachineId(@RequestParam Long machineEvnId) {
@RequestParam Long machineId) { machineEnvService.deleteByMachineId(machineEvnId);
machineEnvService.deleteByMachineId(machineId);
return success(true); return success(true);
} }
@DeleteMapping("/deleteList") @DeleteMapping("/deleteList")
@Operation(summary = "批量删除机器环境变量") @Operation(summary = "批量删除机器环境变量")
public CommonResult deleteList(@RequestParam List<Long> ids){ public CommonResult deleteList(@RequestParam String ids) {
machineEnvService.deleteList(ids); machineEnvService.deleteList(ids);
return success(true); return success(true);
} }
@GetMapping("/getByMachineId") @GetMapping("/getByMachineId")
@Operation(summary = "获取机器的环境变量") @Operation(summary = "获取机器的环境变量")
public CommonResult getByMachineId( public CommonResult getByMachineId(@RequestParam Long machineId) {
@RequestParam Long machineId) {
return success(machineEnvService.getByMachineId(machineId)); return success(machineEnvService.getByMachineId(machineId));
} }
@PostMapping("/list") @PostMapping("/list")
@Operation(summary ="获取环境变量列表") @Operation(summary = "获取环境变量列表")
public CommonResult list(@RequestBody MachineEnvDTO machineEnvDTO) { public CommonResult list(@RequestBody MachineEnvDTO machineEnvDTO) {
return success(machineEnvService.listEnv(machineEnvDTO)); return success(machineEnvService.listEnv(machineEnvDTO));
} }

View File

@ -6,7 +6,6 @@ import cd.casic.module.machine.entity.MachineInfo;
import cd.casic.module.machine.enums.ConnectionStatus; import cd.casic.module.machine.enums.ConnectionStatus;
import cd.casic.module.machine.service.MachineInfoService; import cd.casic.module.machine.service.MachineInfoService;
import cd.casic.module.machine.dto.MachineInfoDto; import cd.casic.module.machine.dto.MachineInfoDto;
import cd.casic.module.machine.pojo.SuccessResponseData;
import cd.casic.module.machine.utils.PageResult; import cd.casic.module.machine.utils.PageResult;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -33,7 +32,7 @@ public class MachineInfoController {
} }
@GetMapping("/list") @PostMapping("/list")
@Operation(summary = "获取机器信息列表") @Operation(summary = "获取机器信息列表")
public CommonResult<PageResult<MachineInfoDto>> list(@RequestBody MachineInfoDto machineInfoDto) { public CommonResult<PageResult<MachineInfoDto>> list(@RequestBody MachineInfoDto machineInfoDto) {
return success(machineInfoService.listMachineInfo(machineInfoDto)); return success(machineInfoService.listMachineInfo(machineInfoDto));
@ -47,26 +46,26 @@ public class MachineInfoController {
@PutMapping("/updateStatus") @PutMapping("/updateStatus")
@Operation(summary = "机器启用/停用") @Operation(summary = "机器启用/停用")
public CommonResult<Boolean> updateStatus(@RequestParam("machineInfoId") Long machineInfoId, @RequestParam("status") String status) { public CommonResult<Boolean> updateStatus(@RequestBody MachineInfoDto machineInfoDto) {
return success(machineInfoService.updateStatus(machineInfoId, status)); return success(machineInfoService.updateStatus(machineInfoDto));
} }
@PutMapping("/bindingSecretKey") @PutMapping("/bindingSecretKey")
@Operation(summary = "绑定密钥") @Operation(summary = "绑定密钥")
public CommonResult<Boolean> bindingSecretKey(@RequestParam("machineInfoId") Long machineInfoId, @RequestParam("secretKeyId") Long secretKeyId) { public CommonResult<Boolean> bindingSecretKey(@RequestBody MachineInfoDto machineInfoDto) {
return success(machineInfoService.bindingSecretKey(machineInfoId, secretKeyId)); return success(machineInfoService.bindingSecretKey(machineInfoDto));
} }
@DeleteMapping("/delete") @DeleteMapping("/delete")
@Operation(summary = "机器信息删除") @Operation(summary = "机器信息删除")
public CommonResult<Boolean> delete(@RequestParam("machineInfoId") Long machineInfoId) { public CommonResult<Boolean> delete(@RequestParam Long machineInfoId) {
machineInfoService.deleteMachineInfo(machineInfoId); machineInfoService.deleteMachineInfo(machineInfoId);
return success(true); return success(true);
} }
@DeleteMapping("/deleteList") @DeleteMapping("/deleteList")
@Operation(summary = "批量删除机器信息") @Operation(summary = "批量删除机器信息")
public CommonResult<Boolean> deleteList(@RequestParam("machineInfoIds") List<Long> machineInfoIds) { public CommonResult<Boolean> deleteList(@RequestParam String machineInfoIds) {
machineInfoService.deleteList(machineInfoIds); machineInfoService.deleteList(machineInfoIds);
return success(true); return success(true);
} }
@ -104,8 +103,8 @@ public class MachineInfoController {
@PostMapping("/execute/{sessionId}") @PostMapping("/execute/{sessionId}")
@Operation(summary = "执行远程命令") @Operation(summary = "执行远程命令")
public CommonResult<String> executeCommand( public CommonResult<String> executeCommand(
@PathVariable String sessionId, @PathVariable String sessionId,
@RequestBody String command) { @RequestBody String command) {
return success(machineInfoService.executeCommand(sessionId, command)); return success(machineInfoService.executeCommand(sessionId, command));
} }
@ -113,18 +112,18 @@ public class MachineInfoController {
@PostMapping("/upload/{sessionId}") @PostMapping("/upload/{sessionId}")
@Operation(summary = "上传文件到远程机器") @Operation(summary = "上传文件到远程机器")
public CommonResult<Boolean> uploadFile( public CommonResult<Boolean> uploadFile(
@PathVariable String sessionId, @PathVariable String sessionId,
@RequestParam String localFilePath, @RequestParam String localFilePath,
@RequestParam String remoteFilePath) { @RequestParam String remoteFilePath) {
return success(machineInfoService.uploadFile(sessionId, localFilePath, remoteFilePath)); return success(machineInfoService.uploadFile(sessionId, localFilePath, remoteFilePath));
} }
@PostMapping("/download/{sessionId}") @PostMapping("/download/{sessionId}")
@Operation(summary = "从远程机器下载文件") @Operation(summary = "从远程机器下载文件")
public CommonResult<Boolean> downloadFile( public CommonResult<Boolean> downloadFile(
@PathVariable String sessionId, @PathVariable String sessionId,
@RequestParam String remoteFilePath, @RequestParam String remoteFilePath,
@RequestParam String localFilePath) { @RequestParam String localFilePath) {
return success(machineInfoService.downloadFile(sessionId, remoteFilePath, localFilePath)); return success(machineInfoService.downloadFile(sessionId, remoteFilePath, localFilePath));
} }
} }

View File

@ -27,41 +27,41 @@ public class MachineProxyController {
private MachineProxyService machineProxyService; private MachineProxyService machineProxyService;
@PostMapping("/register") @PostMapping("/register")
@Operation(summary ="注册新的机器代理") @Operation(summary = "注册新的机器代理")
public CommonResult register(@RequestBody MachineProxyDTO machineProxyDTO) { public CommonResult register(@RequestBody MachineProxyDTO machineProxyDTO) {
machineProxyService.register(machineProxyDTO); machineProxyService.register(machineProxyDTO);
return success(true); return success(true);
} }
@GetMapping("/list") @PostMapping("/list")
@Operation(summary ="获取代理列表") @Operation(summary = "获取代理列表")
public CommonResult list(MachineProxyDTO machineProxyDTO) { public CommonResult list(@RequestBody MachineProxyDTO machineProxyDTO) {
return success(machineProxyService.list(machineProxyDTO)); return success(machineProxyService.list(machineProxyDTO));
} }
@PutMapping("/updateStatus") @PutMapping("/updateStatus")
@Operation(summary ="更新代理状态") @Operation(summary = "更新代理状态")
public CommonResult updateStatus(@RequestBody MachineProxyDTO machineProxyDTO) { public CommonResult updateStatus(@RequestBody MachineProxyDTO machineProxyDTO) {
machineProxyService.updateStatus(machineProxyDTO); machineProxyService.updateStatus(machineProxyDTO);
return success(true); return success(true);
} }
@GetMapping("/statistics/status") @GetMapping("/statistics/status")
@Operation(summary ="获取所有代理的状态统计") @Operation(summary = "获取所有代理的状态统计")
public CommonResult getStatusStatistics() { public CommonResult getStatusStatistics() {
return success(machineProxyService.getStatusStatistics()); return success(machineProxyService.getStatusStatistics());
} }
@PutMapping("/updateConfig") @PutMapping("/update")
@Operation(summary ="更新代理配置") @Operation(summary = "更新代理信息")
public CommonResult updateConfig(@RequestBody MachineProxyDTO machineProxyDTO) { public CommonResult updateConfig(@RequestBody MachineProxyDTO machineProxyDTO) {
machineProxyService.updateConfig(machineProxyDTO); machineProxyService.update(machineProxyDTO);
return success(true); return success(true);
} }
@DeleteMapping("/batch") @DeleteMapping("/batch")
@Operation(summary ="批量删除代理") @Operation(summary = "批量删除代理")
public CommonResult deleteBatch(@RequestParam List<Long> ids) { public CommonResult deleteBatch(@RequestParam String ids) {
machineProxyService.delete(ids); machineProxyService.delete(ids);
return success(true); return success(true);
} }

View File

@ -19,27 +19,10 @@ public class MachineEnvDTO extends PageDto implements Serializable {
private Long id; private Long id;
private String envKey; private String envKey;
private String envValue; private String envValue;
private Integer sensitive;//(1敏感0不敏感)
private String description; private String description;
private Long machineId; private Long machineId;
private Date createDate; private Date createDate;
private Date updateDate; private Date updateDate;
private String sortField; private String sortField;
private String sortDirection; private String sortDirection;
/**
* 获取脱敏后的环境变量值
*/
public String getMaskedValue() {
if (sensitive==1 || envValue == null) {
return envValue;
}
int length = envValue.length();
if (length <= 4) {
return "****";
} else {
return envValue.substring(0, 2) + "****" + envValue.substring(length - 2);
}
}
} }

View File

@ -11,7 +11,7 @@ import java.util.Date;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class MachineInfoDto extends cd.casic.module.machine.dto.PageDto { public class MachineInfoDto extends PageDto {
private Long id; private Long id;
private Date createDate; private Date createDate;
@ -41,4 +41,6 @@ public class MachineInfoDto extends cd.casic.module.machine.dto.PageDto {
private String authenticationType; private String authenticationType;
private String machineInfoType; private String machineInfoType;
private int isProxy;
} }

View File

@ -1,4 +1,5 @@
package cd.casic.module.machine.dto; package cd.casic.module.machine.dto;
import cd.casic.module.machine.enums.MachineProxyStatus; import cd.casic.module.machine.enums.MachineProxyStatus;
import lombok.*; import lombok.*;
@ -23,12 +24,12 @@ public class MachineProxyDTO extends PageDto implements Serializable {
private String version; private String version;
private String status; private String status;
private Date lastHeartbeatTime; private Date lastHeartbeatTime;
private String config;
private String description; private String description;
private String hostIp; private String hostIp;
private String sshPort; private String sshPort;
private Date createDate; private Date createDate;
private Date updateDate; private Date updateDate;
private String password;
/** /**
* 计算代理是否在线 * 计算代理是否在线
@ -40,6 +41,6 @@ public class MachineProxyDTO extends PageDto implements Serializable {
// 假设5分钟内有心跳为在线 // 假设5分钟内有心跳为在线
long fiveMinutes = 5 * 60 * 1000; long fiveMinutes = 5 * 60 * 1000;
return Objects.equals(MachineProxyStatus.ONLINE.getMessage(), status) && return Objects.equals(MachineProxyStatus.ONLINE.getMessage(), status) &&
System.currentTimeMillis() - lastHeartbeatTime.getTime() < fiveMinutes; System.currentTimeMillis() - lastHeartbeatTime.getTime() < fiveMinutes;
} }
} }

View File

@ -3,7 +3,7 @@ package cd.casic.module.machine.dto;
import lombok.Data; import lombok.Data;
@Data @Data
public class PageDto{ public class PageDto {
private int pageIndex = 1; private int pageIndex = 1;
private int pageSize = 10; private int pageSize = 10;

View File

@ -31,4 +31,6 @@ public class SecretKeyDto extends PageDto {
private Date createDate; private Date createDate;
private Date updateDate; private Date updateDate;
private List<Long> machineInfoIds;
} }

View File

@ -34,11 +34,6 @@ public class MachineEnv extends BaseEntity implements Serializable {
*/ */
private String envValue; private String envValue;
/**
* 是否敏感
*/
@TableField("`sensitive`")
private Integer sensitive;//(1敏感0不敏感)
/** /**
* 描述信息 * 描述信息

View File

@ -15,7 +15,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@TableName(value = "machine_info") @TableName(value = "machine_info")
public class MachineInfo extends BaseEntity{ public class MachineInfo extends BaseEntity {
@TableField(value = "name") @TableField(value = "name")
private String name; private String name;
@ -63,4 +63,7 @@ public class MachineInfo extends BaseEntity{
@TableField(exist = false) @TableField(exist = false)
private AuthenticationType authenticationType; private AuthenticationType authenticationType;
@TableField(value = "is_proxy")
private int isProxy;
} }

View File

@ -1,7 +1,10 @@
package cd.casic.module.machine.entity; package cd.casic.module.machine.entity;
import cd.casic.module.machine.enums.MachineProxyStatus;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import cd.casic.module.machine.enums.MachineInfoStatus; import cd.casic.module.machine.enums.MachineInfoStatus;
import cd.casic.module.machine.enums.MachineProxyType; import cd.casic.module.machine.enums.MachineProxyType;
import jakarta.validation.Valid;
import lombok.*; import lombok.*;
import java.io.Serializable; import java.io.Serializable;
@ -19,8 +22,10 @@ import java.util.Date;
public class MachineProxy extends BaseEntity implements Serializable { public class MachineProxy extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableField(value = "host_ip")
private String hostIp; private String hostIp;
@TableField(value = "ssh_port")
private String sshPort; private String sshPort;
/** /**
@ -29,37 +34,39 @@ public class MachineProxy extends BaseEntity implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private MachineProxyType proxyType; private MachineProxyType proxyType;
@TableField(value = "proxy_type_code")
private int proxyTypeCode; private int proxyTypeCode;
/** /**
* 代理版本 * 代理版本
*/ */
@TableField(value = "version")
private String version; private String version;
/** /**
* 代理状态 (online, offline, installing, updating, error) * 代理状态 (online, offline, installing, updating, error)
*/ */
@TableField(exist = false) @TableField(exist = false)
private MachineInfoStatus status; private MachineProxyStatus status;
@TableField(value = "status_code")
private int statusCode; private int statusCode;
@TableField(value = "username")
private String username;
/** /**
* 最后心跳时间 * 最后心跳时间
*/ */
private Date lastHeartbeatTime; private Date lastHeartbeatTime;
/** @TableField(value = "password")
* 代理配置 (JSON格式) private String password;
*/
private String config;
/** /**
* 描述信息 * 描述信息
*/ */
@TableField(value = "description")
private String description; private String description;
} }

View File

@ -10,11 +10,11 @@ public enum MachineProxyStatus implements CodeEnum {
/** /**
* 代理状态 (online, offline, installing, updating, error) * 代理状态 (online, offline, installing, updating, error)
*/ */
ONLINE(1,"online"), ONLINE(1, "online"),
OFFLINE(2,"offline"), OFFLINE(2, "offline"),
INSTALLING(3,"installing"), INSTALLING(3, "installing"),
UPDATING(4,"updating"), UPDATING(4, "updating"),
ERROR(5,"error"); ERROR(5, "error");
private final int code; private final int code;

View File

@ -7,9 +7,9 @@ import lombok.Getter;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum MachineProxyType implements CodeEnum { public enum MachineProxyType implements CodeEnum {
HTTP(1,"http"), HTTP(1, "http"),
SOCKS4(2,"socks4"), SOCKS4(2, "socks4"),
SOCKS5(3,"socks5"); SOCKS5(3, "socks5");
private final int code; private final int code;

View File

@ -7,8 +7,8 @@ import lombok.Getter;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum RequestExceptionEnum implements CodeEnum { public enum RequestExceptionEnum implements CodeEnum {
REQUEST_TYPE_NOT_JSON(1,"传递参数格式错误请使用json格式"), REQUEST_TYPE_NOT_JSON(1, "传递参数格式错误请使用json格式"),
REQUEST_JSON_ERROR(2,"json格式错误"), REQUEST_JSON_ERROR(2, "json格式错误"),
REQUEST_METHOD_NOT_POST(3, "不支持该请求方法请求方法应为POST"), REQUEST_METHOD_NOT_POST(3, "不支持该请求方法请求方法应为POST"),
REQUEST_METHOD_NOT_GET(4, "不支持该请求方法请求方法应为GET"), REQUEST_METHOD_NOT_GET(4, "不支持该请求方法请求方法应为GET"),
PARAM_ERROR(5, "参数错误"); PARAM_ERROR(5, "参数错误");

View File

@ -62,13 +62,13 @@ public class ConnectionSession implements AutoCloseable {
doConnect(); doConnect();
status = ConnectionStatus.CONNECTED; status = ConnectionStatus.CONNECTED;
log.info("SSH connection established successfully to {} (attempt {}/{})", log.info("SSH connection established successfully to {} (attempt {}/{})",
machineInfo.getHostIp(), attempt, RETRY_COUNT); machineInfo.getHostIp(), attempt, RETRY_COUNT);
return; return;
} catch (JSchException e) { } catch (JSchException e) {
lastException = e; lastException = e;
status = ConnectionStatus.CONNECTION_ERROR; status = ConnectionStatus.CONNECTION_ERROR;
log.error("SSH connection attempt {}/{} failed: {}", log.error("SSH connection attempt {}/{} failed: {}",
attempt, RETRY_COUNT, e.getMessage()); attempt, RETRY_COUNT, e.getMessage());
// 认证失败直接退出无需重试 // 认证失败直接退出无需重试
if (e.getMessage().contains("Auth fail")) { if (e.getMessage().contains("Auth fail")) {
@ -105,9 +105,9 @@ public class ConnectionSession implements AutoCloseable {
// 创建SSH会话 // 创建SSH会话
sshSession = jsch.getSession( sshSession = jsch.getSession(
machineInfo.getUsername(), machineInfo.getUsername(),
machineInfo.getHostIp(), machineInfo.getHostIp(),
machineInfo.getSshPort() != null ? machineInfo.getSshPort() : 22 machineInfo.getSshPort() != null ? machineInfo.getSshPort() : 22
); );
// 配置连接参数 // 配置连接参数
@ -120,7 +120,7 @@ public class ConnectionSession implements AutoCloseable {
/** /**
* 配置认证方式密码或密钥 * 配置认证方式密码或密钥
*/ */
private void configureAuthentication(JSch jsch) throws JSchException{ private void configureAuthentication(JSch jsch) throws JSchException {
if (machineInfo.getAuthenticationType() == AuthenticationType.SECRET_KEY) { if (machineInfo.getAuthenticationType() == AuthenticationType.SECRET_KEY) {
// 密钥认证 // 密钥认证
if (machineInfo.getSecretKeyId() == null) { if (machineInfo.getSecretKeyId() == null) {
@ -134,10 +134,10 @@ public class ConnectionSession implements AutoCloseable {
// 加载私钥支持密码短语可从配置中获取 // 加载私钥支持密码短语可从配置中获取
jsch.addIdentity( jsch.addIdentity(
machineInfo.getName(), machineInfo.getName(),
privateKeyContent.getBytes(StandardCharsets.UTF_8), privateKeyContent.getBytes(StandardCharsets.UTF_8),
null, null,
null // 密码短语可为null null // 密码短语可为null
); );
} else if (machineInfo.getAuthenticationType() == AuthenticationType.PASSWORD) { } else if (machineInfo.getAuthenticationType() == AuthenticationType.PASSWORD) {
// 密码认证 // 密码认证
@ -158,7 +158,7 @@ public class ConnectionSession implements AutoCloseable {
// 安全增强默认验证主机密钥 // 安全增强默认验证主机密钥
if (isTrustedEnvironment()) { if (isTrustedEnvironment()) {
log.warn("Running in trusted environment - disabling strict host key checking for {}", log.warn("Running in trusted environment - disabling strict host key checking for {}",
machineInfo.getHostIp()); machineInfo.getHostIp());
config.put("StrictHostKeyChecking", "no"); config.put("StrictHostKeyChecking", "no");
} else { } else {
config.put("StrictHostKeyChecking", "yes"); config.put("StrictHostKeyChecking", "yes");
@ -261,7 +261,7 @@ public class ConnectionSession implements AutoCloseable {
// 使用线程中断机制实现超时控制 // 使用线程中断机制实现超时控制
Thread readerThread = new Thread(() -> { Thread readerThread = new Thread(() -> {
int bytesRead ; int bytesRead;
try { try {
while ((bytesRead = inputStream.read(buffer)) != -1) { while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead); outputStream.write(buffer, 0, bytesRead);
@ -349,10 +349,10 @@ public class ConnectionSession implements AutoCloseable {
// 使用更健壮的上传方式 // 使用更健壮的上传方式
channel.put( channel.put(
new FileInputStream(localFile), new FileInputStream(localFile),
remoteFilePath, remoteFilePath,
new ProgressMonitorAdapter(localFile.length()), new ProgressMonitorAdapter(localFile.length()),
ChannelSftp.OVERWRITE ChannelSftp.OVERWRITE
); );
uploadSuccess = true; uploadSuccess = true;
@ -361,7 +361,7 @@ public class ConnectionSession implements AutoCloseable {
} catch (SftpException e) { } catch (SftpException e) {
log.error("SFTP error during file upload ({} -> {}): {}", log.error("SFTP error during file upload ({} -> {}): {}",
localFilePath, remoteFilePath, e.getMessage(), e); localFilePath, remoteFilePath, e.getMessage(), e);
throw new IOException("SFTP error: " + e.getMessage(), e); throw new IOException("SFTP error: " + e.getMessage(), e);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
log.error("Local file not found during upload: {}", localFilePath, e); log.error("Local file not found during upload: {}", localFilePath, e);
@ -418,16 +418,16 @@ public class ConnectionSession implements AutoCloseable {
// 执行下载并监控进度 // 执行下载并监控进度
channel.get( channel.get(
remoteFilePath, remoteFilePath,
new FileOutputStream(tempFile).toString(), new FileOutputStream(tempFile).toString(),
new ProgressMonitorAdapter(fileSize), new ProgressMonitorAdapter(fileSize),
ChannelSftp.OVERWRITE ChannelSftp.OVERWRITE
); );
// 验证下载完整性 // 验证下载完整性
if (tempFile.length() != fileSize) { if (tempFile.length() != fileSize) {
throw new IOException("Download incomplete: expected " + fileSize + throw new IOException("Download incomplete: expected " + fileSize +
" bytes, but got " + tempFile.length() + " bytes"); " bytes, but got " + tempFile.length() + " bytes");
} }
// 重命名临时文件为目标文件原子操作 // 重命名临时文件为目标文件原子操作
@ -441,7 +441,7 @@ public class ConnectionSession implements AutoCloseable {
} catch (SftpException e) { } catch (SftpException e) {
log.error("SFTP error during file download ({} -> {}): {}", log.error("SFTP error during file download ({} -> {}): {}",
remoteFilePath, localFilePath, e.getMessage(), e); remoteFilePath, localFilePath, e.getMessage(), e);
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
throw new FileNotFoundException("Remote file not found: " + remoteFilePath); throw new FileNotFoundException("Remote file not found: " + remoteFilePath);
} }
@ -482,11 +482,13 @@ public class ConnectionSession implements AutoCloseable {
log.debug("Created remote directory: {}", directory); log.debug("Created remote directory: {}", directory);
} }
} }
// 获取路径的父目录 // 获取路径的父目录
private String getParentDirectory(String path) { private String getParentDirectory(String path) {
int lastSlash = path.lastIndexOf('/'); int lastSlash = path.lastIndexOf('/');
return lastSlash > 0 ? path.substring(0, lastSlash) : ""; return lastSlash > 0 ? path.substring(0, lastSlash) : "";
} }
// 断开SFTP通道 // 断开SFTP通道
private void disconnectChannel(Channel channel) { private void disconnectChannel(Channel channel) {
if (channel != null && channel.isConnected()) { if (channel != null && channel.isConnected()) {
@ -513,6 +515,7 @@ public class ConnectionSession implements AutoCloseable {
disconnectChannel(channel); disconnectChannel(channel);
} }
} }
// 增强的进度监控器 // 增强的进度监控器
private static class ProgressMonitorAdapter implements SftpProgressMonitor { private static class ProgressMonitorAdapter implements SftpProgressMonitor {
private final long totalBytes; private final long totalBytes;
@ -538,7 +541,7 @@ public class ConnectionSession implements AutoCloseable {
String speedStr = formatTransferSpeed(speed); String speedStr = formatTransferSpeed(speed);
log.debug("Upload progress: {}% ({}/{} bytes, {})", log.debug("Upload progress: {}% ({}/{} bytes, {})",
progress, bytesWritten, totalBytes, speedStr); progress, bytesWritten, totalBytes, speedStr);
lastProgress = progress; lastProgress = progress;
} }
@ -552,7 +555,7 @@ public class ConnectionSession implements AutoCloseable {
String speedStr = formatTransferSpeed(speed); String speedStr = formatTransferSpeed(speed);
log.info("Upload completed: {} bytes in {} ms (avg speed: {})", log.info("Upload completed: {} bytes in {} ms (avg speed: {})",
totalBytes, elapsedTime, speedStr); totalBytes, elapsedTime, speedStr);
} }
@Override @Override
@ -575,13 +578,12 @@ public class ConnectionSession implements AutoCloseable {
} }
/** /**
* 检查连接状态 * 检查连接状态
*/ */
public ConnectionStatus getStatus() { public ConnectionStatus getStatus() {
if (status == ConnectionStatus.CONNECTED && if (status == ConnectionStatus.CONNECTED &&
(sshSession == null || !sshSession.isConnected())) { (sshSession == null || !sshSession.isConnected())) {
status = ConnectionStatus.DISCONNECTED; status = ConnectionStatus.DISCONNECTED;
} }
return status; return status;
@ -592,8 +594,8 @@ public class ConnectionSession implements AutoCloseable {
*/ */
public boolean isConnected() { public boolean isConnected() {
return status == ConnectionStatus.CONNECTED && return status == ConnectionStatus.CONNECTED &&
sshSession != null && sshSession != null &&
sshSession.isConnected(); sshSession.isConnected();
} }

View File

@ -1,26 +0,0 @@
package cd.casic.module.machine.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class ErrorResponseData extends ResponseData {
/**
* 异常的具体类名称
*/
private String exceptionClazz;
public ErrorResponseData(String message) {
super(false, DEFAULT_ERROR_CODE, message, null);
}
public ErrorResponseData(Integer code, String message) {
super(false, code, message, null);
}
public ErrorResponseData(Integer code, String message, Object object) {
super(false, code, message, object);
}
}

View File

@ -1,72 +0,0 @@
package cd.casic.module.machine.pojo;
import lombok.Data;
/**
* 响应结果数据
*/
@Data
public class ResponseData {
public static final String DEFAULT_SUCCESS_MESSAGE = "请求成功";
public static final String DEFAULT_ERROR_MESSAGE = "网络异常";
public static final Integer DEFAULT_SUCCESS_CODE = 200;
public static final Integer DEFAULT_ERROR_CODE = 500;
/**
* 请求是否成功
*/
private Boolean success;
/**
* 响应状态码
*/
private Integer code;
/**
* 响应信息
*/
private String message;
/**
* 响应对象
*/
private Object data;
public ResponseData() {
}
public ResponseData(Boolean success, Integer code, String message, Object data) {
this.success = success;
this.code = code;
this.message = message;
this.data = data;
}
public static SuccessResponseData success() {
return new SuccessResponseData();
}
public static SuccessResponseData success(Object object) {
return new SuccessResponseData(object);
}
public static SuccessResponseData success(Integer code, String message, Object object) {
return new SuccessResponseData(code, message, object);
}
public static ErrorResponseData error(String message) {
return new ErrorResponseData(message);
}
public static ErrorResponseData error(Integer code, String message) {
return new ErrorResponseData(code, message);
}
public static ErrorResponseData error(Integer code, String message, Object object) {
return new ErrorResponseData(code, message, object);
}
}

View File

@ -1,16 +0,0 @@
package cd.casic.module.machine.pojo;
public class SuccessResponseData extends ResponseData {
public SuccessResponseData() {
super(true, DEFAULT_SUCCESS_CODE, DEFAULT_SUCCESS_MESSAGE, null);
}
public SuccessResponseData(Object object) {
super(true, DEFAULT_SUCCESS_CODE, DEFAULT_SUCCESS_MESSAGE, object);
}
public SuccessResponseData(Integer code, String message, Object object) {
super(true, code, message, object);
}
}

View File

@ -16,14 +16,15 @@ public interface MachineEnvService extends IService<MachineEnv> {
* 创建或更新机器的环境变量一对一关系 * 创建或更新机器的环境变量一对一关系
*/ */
boolean add(MachineEnvDTO machineEnvDTO); boolean add(MachineEnvDTO machineEnvDTO);
/** /**
* 删除机器的环境变量 * 删除机器的环境变量
* @param machineId 机器ID
*/ */
void deleteByMachineId(Long machineId); void deleteByMachineId(Long machineEvnId);
/** /**
* 获取机器的环境变量 * 获取机器的环境变量
*
* @param machineId 机器ID * @param machineId 机器ID
* @return 环境变量DTO * @return 环境变量DTO
*/ */
@ -34,7 +35,7 @@ public interface MachineEnvService extends IService<MachineEnv> {
*/ */
PageResult<MachineEnvDTO> listEnv(MachineEnvDTO machineEnvDTO); PageResult<MachineEnvDTO> listEnv(MachineEnvDTO machineEnvDTO);
void deleteList(List<Long> ids); void deleteList(String ids);
boolean update(MachineEnvDTO machineEnvDTO); boolean update(MachineEnvDTO machineEnvDTO);
} }

View File

@ -16,18 +16,18 @@ public interface MachineInfoService extends IService<MachineInfo> {
boolean updateMachineInfo(MachineInfoDto machineInfoDto); boolean updateMachineInfo(MachineInfoDto machineInfoDto);
boolean updateStatus(Long machineInfoId, String status); boolean updateStatus(MachineInfoDto machineInfoDto);
boolean bindingSecretKey( Long machineInfoId, Long secretKeyId); boolean bindingSecretKey(MachineInfoDto machineInfoDto);
void deleteList(List<Long> machineInfoIds); void deleteList(String machineInfoIds);
void deleteMachineInfo(Long machineInfoId); void deleteMachineInfo(Long machineInfoId);
/** /**
* 测试机器连接 * 测试机器连接
*
* @param machineInfo 机器信息 * @param machineInfo 机器信息
* @return 连接是否成功 * @return 连接是否成功
*/ */
@ -35,6 +35,7 @@ public interface MachineInfoService extends IService<MachineInfo> {
/** /**
* 获取机器连接状态 * 获取机器连接状态
*
* @param machineName 机器名称 * @param machineName 机器名称
* @return 连接状态 * @return 连接状态
*/ */
@ -42,12 +43,14 @@ public interface MachineInfoService extends IService<MachineInfo> {
/** /**
* 获取所有连接状态 * 获取所有连接状态
*
* @return 机器名称到连接状态的映射 * @return 机器名称到连接状态的映射
*/ */
Map<String, ConnectionStatus> getAllConnectionStatus(); Map<String, ConnectionStatus> getAllConnectionStatus();
/** /**
* 建立机器连接 * 建立机器连接
*
* @param machineInfo 机器信息 * @param machineInfo 机器信息
* @return 连接会话ID * @return 连接会话ID
*/ */
@ -55,6 +58,7 @@ public interface MachineInfoService extends IService<MachineInfo> {
/** /**
* 断开机器连接 * 断开机器连接
*
* @param sessionId 会话ID * @param sessionId 会话ID
* @return 操作结果 * @return 操作结果
*/ */
@ -62,16 +66,18 @@ public interface MachineInfoService extends IService<MachineInfo> {
/** /**
* 执行远程命令 * 执行远程命令
*
* @param sessionId 会话ID * @param sessionId 会话ID
* @param command 命令 * @param command 命令
* @return 命令执行结果 * @return 命令执行结果
*/ */
String executeCommand(String sessionId, String command); String executeCommand(String sessionId, String command);
/** /**
* 上传文件到远程机器 * 上传文件到远程机器
* @param sessionId 会话ID *
* @param localFilePath 本地文件路径 * @param sessionId 会话ID
* @param localFilePath 本地文件路径
* @param remoteFilePath 远程文件路径 * @param remoteFilePath 远程文件路径
* @return 操作结果 * @return 操作结果
*/ */
@ -79,9 +85,10 @@ public interface MachineInfoService extends IService<MachineInfo> {
/** /**
* 从远程机器下载文件 * 从远程机器下载文件
* @param sessionId 会话ID *
* @param sessionId 会话ID
* @param remoteFilePath 远程文件路径 * @param remoteFilePath 远程文件路径
* @param localFilePath 本地文件路径 * @param localFilePath 本地文件路径
* @return 操作结果 * @return 操作结果
*/ */
boolean downloadFile(String sessionId, String remoteFilePath, String localFilePath); boolean downloadFile(String sessionId, String remoteFilePath, String localFilePath);

View File

@ -1,4 +1,5 @@
package cd.casic.module.machine.service; package cd.casic.module.machine.service;
import cd.casic.module.machine.dto.MachineProxyDTO; import cd.casic.module.machine.dto.MachineProxyDTO;
import cd.casic.module.machine.entity.MachineProxy; import cd.casic.module.machine.entity.MachineProxy;
import cd.casic.module.machine.utils.PageResult; import cd.casic.module.machine.utils.PageResult;
@ -22,7 +23,6 @@ public interface MachineProxyService extends IService<MachineProxy> {
boolean updateStatus(MachineProxyDTO machineProxyDTO); boolean updateStatus(MachineProxyDTO machineProxyDTO);
/** /**
* 获取所有代理的状态统计 * 获取所有代理的状态统计
* *
@ -33,15 +33,15 @@ public interface MachineProxyService extends IService<MachineProxy> {
/** /**
* 更新代理配置 * 更新代理配置
*/ */
void updateConfig(MachineProxyDTO machineProxyDTO); void update(MachineProxyDTO machineProxyDTO);
/** /**
* 批量删除代理 * 批量删除代理
*
* @param proxyIds 代理ID列表 * @param proxyIds 代理ID列表
*/ */
void delete(List<Long> proxyIds); void delete(String proxyIds);
PageResult<MachineProxyDTO> list(MachineProxyDTO machineProxyDTO); PageResult<MachineProxyDTO> list(MachineProxyDTO machineProxyDTO);
} }

View File

@ -1,4 +1,5 @@
package cd.casic.module.machine.service.impl; package cd.casic.module.machine.service.impl;
import cd.casic.module.machine.dto.MachineEnvDTO; import cd.casic.module.machine.dto.MachineEnvDTO;
import cd.casic.module.machine.entity.MachineEnv; import cd.casic.module.machine.entity.MachineEnv;
import cd.casic.module.machine.exception.ServiceException; import cd.casic.module.machine.exception.ServiceException;
@ -15,6 +16,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -31,13 +33,13 @@ public class MachineEnvServiceImpl extends ServiceImpl<MachineEnvMapper, Machine
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public boolean add(MachineEnvDTO machineEnvDTO) { public boolean add(MachineEnvDTO machineEnvDTO) {
// 参数校验 // 参数校验
if (machineEnvDTO==null) { if (machineEnvDTO == null) {
throw new ServiceException(ServiceException.MACHINE_ENV_NULL,"环境变量不能为空"); throw new ServiceException(ServiceException.MACHINE_ENV_NULL, "环境变量不能为空");
} }
// 检查键是否合法 // 检查键是否合法
if (!isValidKey(machineEnvDTO.getEnvKey())) { if (!isValidKey(machineEnvDTO.getEnvKey())) {
throw new ServiceException(ServiceException.MACHINE_ENV_KEY_ILLEGAL,"环境变量键不合法"); throw new ServiceException(ServiceException.MACHINE_ENV_KEY_ILLEGAL, "环境变量键不合法");
} }
// 判断是否敏感变量 // 判断是否敏感变量
@ -49,12 +51,11 @@ public class MachineEnvServiceImpl extends ServiceImpl<MachineEnvMapper, Machine
} }
@Override @Override
public void deleteByMachineId(Long machineId) { public void deleteByMachineId(Long machineEvnId) {
this.removeById(machineId); this.removeById(machineEvnId);
} }
@Override @Override
public MachineEnvDTO getByMachineId(Long machineId) { public MachineEnvDTO getByMachineId(Long machineId) {
if (machineId == null) { if (machineId == null) {
@ -62,8 +63,8 @@ public class MachineEnvServiceImpl extends ServiceImpl<MachineEnvMapper, Machine
} }
MachineEnv machineEnv = getOne( MachineEnv machineEnv = getOne(
new LambdaQueryWrapper<MachineEnv>() new LambdaQueryWrapper<MachineEnv>()
.eq(MachineEnv::getMachineId, machineId) .eq(MachineEnv::getMachineId, machineId)
); );
return machineEnv != null ? convertToDTO(machineEnv) : null; return machineEnv != null ? convertToDTO(machineEnv) : null;
@ -87,11 +88,6 @@ public class MachineEnvServiceImpl extends ServiceImpl<MachineEnvMapper, Machine
queryWrapper.like(MachineEnv::getMachineId, machineEnvDTO.getMachineId()); queryWrapper.like(MachineEnv::getMachineId, machineEnvDTO.getMachineId());
} }
// 是否敏感
if (!StringUtils.isEmpty(machineEnvDTO.getSensitive())) {
queryWrapper.eq(MachineEnv::getSensitive, machineEnvDTO.getSensitive());
}
// 创建时间范围查询 // 创建时间范围查询
if (!StringUtils.isEmpty(machineEnvDTO.getCreateDate())) { if (!StringUtils.isEmpty(machineEnvDTO.getCreateDate())) {
queryWrapper.ge(MachineEnv::getCreateDate, machineEnvDTO.getCreateDate()); queryWrapper.ge(MachineEnv::getCreateDate, machineEnvDTO.getCreateDate());
@ -119,28 +115,33 @@ public class MachineEnvServiceImpl extends ServiceImpl<MachineEnvMapper, Machine
// 转换结果 // 转换结果
List<MachineEnvDTO> dtoList = page.getRecords().stream() List<MachineEnvDTO> dtoList = page.getRecords().stream()
.map(this::convertToDTO) .map(this::convertToDTO)
.collect(Collectors.toList()); .collect(Collectors.toList());
// 构建分页结果 // 构建分页结果
return PageResult.<MachineEnvDTO>builder() return PageResult.<MachineEnvDTO>builder()
.pageNum(page.getCurrent()) .pageNum(page.getCurrent())
.pageSize(page.getSize()) .pageSize(page.getSize())
.total(page.getTotal()) .total(page.getTotal())
.pages(page.getPages()) .pages(page.getPages())
.list(dtoList) .list(dtoList)
.build(); .build();
} }
@Override @Override
public void deleteList(List<Long> ids) { public void deleteList(String ids) {
this.machineEnvMapper.deleteBatchIds(ids); List<Long> machineEnvIds = Arrays.stream(ids.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(Long::parseLong)
.toList();
this.machineEnvMapper.deleteBatchIds(machineEnvIds);
} }
@Override @Override
public boolean update(MachineEnvDTO machineEnvDTO) { public boolean update(MachineEnvDTO machineEnvDTO) {
MachineEnv machineEnv = new MachineEnv(); MachineEnv machineEnv = new MachineEnv();
BeanUtils.copyProperties(machineEnvDTO,machineEnv); BeanUtils.copyProperties(machineEnvDTO, machineEnv);
return this.updateById(machineEnv); return this.updateById(machineEnv);
} }
@ -150,7 +151,6 @@ public class MachineEnvServiceImpl extends ServiceImpl<MachineEnvMapper, Machine
dto.setId(machineEnv.getId()); dto.setId(machineEnv.getId());
dto.setEnvKey(machineEnv.getEnvKey()); dto.setEnvKey(machineEnv.getEnvKey());
dto.setEnvValue(machineEnv.getEnvValue()); dto.setEnvValue(machineEnv.getEnvValue());
dto.setSensitive(machineEnv.getSensitive());
dto.setDescription(machineEnv.getDescription()); dto.setDescription(machineEnv.getDescription());
dto.setCreateDate(machineEnv.getCreateDate()); dto.setCreateDate(machineEnv.getCreateDate());
dto.setUpdateDate(machineEnv.getUpdateDate()); dto.setUpdateDate(machineEnv.getUpdateDate());
@ -169,6 +169,6 @@ public class MachineEnvServiceImpl extends ServiceImpl<MachineEnvMapper, Machine
} }
String upperKey = key.toUpperCase(); String upperKey = key.toUpperCase();
return upperKey.contains("PASSWORD") || upperKey.contains("SECRET") || return upperKey.contains("PASSWORD") || upperKey.contains("SECRET") ||
upperKey.contains("TOKEN") || upperKey.contains("KEY"); upperKey.contains("TOKEN") || upperKey.contains("KEY");
} }
} }

View File

@ -1,4 +1,5 @@
package cd.casic.module.machine.service.impl; package cd.casic.module.machine.service.impl;
import cd.casic.module.machine.dto.MachineProxyDTO; import cd.casic.module.machine.dto.MachineProxyDTO;
import cd.casic.module.machine.entity.MachineProxy; import cd.casic.module.machine.entity.MachineProxy;
import cd.casic.module.machine.enums.MachineProxyStatus; import cd.casic.module.machine.enums.MachineProxyStatus;
@ -18,6 +19,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -38,7 +40,7 @@ public class MachineProxyServiceImpl extends ServiceImpl<MachineProxyMapper, Mac
BeanUtils.copyProperties(machineProxyDTO, proxy); BeanUtils.copyProperties(machineProxyDTO, proxy);
proxy.setProxyTypeCode(EnumUtils.getEnumByMessage(machineProxyDTO.getProxyType(), MachineProxyType.class).getCode()); proxy.setProxyTypeCode(EnumUtils.getEnumByMessage(machineProxyDTO.getProxyType(), MachineProxyType.class).getCode());
proxy.setVersion("1.0.0"); proxy.setVersion("1.0.0");
proxy.setStatusCode(MachineProxyStatus.INSTALLING.getCode()); proxy.setStatusCode(MachineProxyStatus.ONLINE.getCode());
return save(proxy); return save(proxy);
} }
@ -46,24 +48,23 @@ public class MachineProxyServiceImpl extends ServiceImpl<MachineProxyMapper, Mac
public boolean updateStatus(MachineProxyDTO machineProxyDTO) { public boolean updateStatus(MachineProxyDTO machineProxyDTO) {
// 参数校验 // 参数校验
if (machineProxyDTO == null) { if (machineProxyDTO == null) {
throw new ServiceException(ServiceException.MACHINE_PROXY_DTO_NULL,"MachineProxyDTO对象为空"); throw new ServiceException(ServiceException.MACHINE_PROXY_DTO_NULL, "MachineProxyDTO对象为空");
} }
// 查询代理 // 查询代理
MachineProxy proxy = this.getById(machineProxyDTO.getId()); MachineProxy proxy = this.getById(machineProxyDTO.getId());
if (proxy == null) { if (proxy == null) {
throw new ServiceException(ServiceException.MACHINE_PROXY_NULL,"代理不存在"); throw new ServiceException(ServiceException.MACHINE_PROXY_NULL, "代理不存在");
} }
// 更新状态 // 更新状态
proxy.setStatusCode(EnumUtils.getEnumByMessage(machineProxyDTO.getStatus(),MachineProxyStatus.class).getCode()); proxy.setStatusCode(EnumUtils.getEnumByMessage(machineProxyDTO.getStatus(), MachineProxyStatus.class).getCode());
proxy.setUpdateDate(new Date()); proxy.setUpdateDate(new Date());
return updateById(proxy); return updateById(proxy);
} }
@Override @Override
public Map<String, Long> getStatusStatistics() { public Map<String, Long> getStatusStatistics() {
List<MachineProxy> proxyList = list(); List<MachineProxy> proxyList = list();
@ -72,57 +73,47 @@ public class MachineProxyServiceImpl extends ServiceImpl<MachineProxyMapper, Mac
return Collections.emptyMap(); return Collections.emptyMap();
} }
return proxyList.stream() return proxyList.stream()
.map(proxy -> EnumUtils.getEnumByCode(proxy.getStatusCode(), MachineProxyStatus.class).getMessage()) .map(proxy -> EnumUtils.getEnumByCode(proxy.getStatusCode(), MachineProxyStatus.class).getMessage())
.collect(Collectors.groupingBy( .collect(Collectors.groupingBy(
Function.identity(), Function.identity(),
Collectors.counting() // 统计每个分组的元素数量 Collectors.counting() // 统计每个分组的元素数量
)); ));
} }
@Override @Override
public void updateConfig(MachineProxyDTO machineProxyDTO) { public void update(MachineProxyDTO machineProxyDTO) {
// 参数校验 // 参数校验
if (machineProxyDTO == null) { if (machineProxyDTO == null) {
throw new ServiceException(ServiceException.MACHINE_PROXY_DTO_NULL,"MachineProxyDTO对象为空"); throw new ServiceException(ServiceException.MACHINE_PROXY_DTO_NULL, "MachineProxyDTO对象为空");
} }
MachineProxy machineProxy = new MachineProxy();
// 查询代理 BeanUtils.copyProperties(machineProxyDTO, machineProxy);
MachineProxy proxy = getById(machineProxyDTO.getId()); if (machineProxyDTO.getProxyType() != null && !machineProxyDTO.getProxyType().isEmpty()) {
machineProxy.setProxyTypeCode(EnumUtils.getEnumByMessage(machineProxyDTO.getProxyType(), MachineProxyType.class).getCode());
if (proxy == null) {
throw new ServiceException(ServiceException.MACHINE_PROXY_NULL,"代理不存在");
} }
// 更新配置 if (machineProxyDTO.getStatus() != null && !machineProxyDTO.getStatus().isEmpty()) {
proxy.setConfig(machineProxyDTO.getConfig()); machineProxy.setStatusCode(EnumUtils.getEnumByMessage(machineProxyDTO.getStatus(), MachineProxyStatus.class).getCode());
proxy.setUpdateDate(new Date()); }
updateById(proxy); this.updateById(machineProxy);
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void delete(List<Long> ids) { public void delete(String ids) {
List<Long> machineProxyIds = Arrays.stream(ids.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(Long::parseLong)
.toList();
// 参数校验 // 参数校验
if (CollectionUtils.isEmpty(ids)) { if (CollectionUtils.isEmpty(machineProxyIds)) {
throw new ServiceException(ServiceException.PARAMETER_ERROR,"参数错误"); throw new ServiceException(ServiceException.PARAMETER_ERROR, "参数错误");
} }
// 查询在线代理
List<MachineProxy> onlineProxies = list(new LambdaQueryWrapper<MachineProxy>()
.in(MachineProxy::getId, ids)
.eq(MachineProxy::getStatusCode, MachineProxyStatus.ONLINE.getCode()));
if (!CollectionUtils.isEmpty(onlineProxies)) {
List<Long> onlineIds = onlineProxies.stream()
.map(MachineProxy::getId)
.collect(Collectors.toList());
throw new IllegalArgumentException("以下代理处于在线状态,无法删除: " + String.join( ",", (CharSequence) onlineIds));
}
// 批量逻辑删除 // 批量逻辑删除
remove(new LambdaQueryWrapper<MachineProxy>() remove(new LambdaQueryWrapper<MachineProxy>()
.in(MachineProxy::getId, ids)); .in(MachineProxy::getId, machineProxyIds)
.ne(MachineProxy::getStatus, MachineProxyStatus.ONLINE.getCode()));
} }
@Override @Override
@ -132,37 +123,40 @@ public class MachineProxyServiceImpl extends ServiceImpl<MachineProxyMapper, Mac
List<MachineProxyDTO> machineProxyDtos = page.getRecords().stream().map(machineProxy -> { List<MachineProxyDTO> machineProxyDtos = page.getRecords().stream().map(machineProxy -> {
MachineProxyDTO dto = new MachineProxyDTO(); MachineProxyDTO dto = new MachineProxyDTO();
BeanUtils.copyProperties(machineProxy, dto); BeanUtils.copyProperties(machineProxy, dto);
dto.setProxyType(EnumUtils.getEnumByCode(machineProxy.getStatusCode(), MachineProxyType.class).getMessage()); dto.setProxyType(EnumUtils.getEnumByCode(machineProxy.getProxyTypeCode(), MachineProxyType.class).getMessage());
dto.setStatus(EnumUtils.getEnumByCode(machineProxy.getStatusCode(), MachineProxyStatus.class).getMessage()); dto.setStatus(EnumUtils.getEnumByCode(machineProxy.getStatusCode(), MachineProxyStatus.class).getMessage());
return dto; return dto;
}).toList(); }).toList();
return new PageResult<>( return new PageResult<>(
page.getCurrent(), page.getCurrent(),
page.getSize(), page.getSize(),
page.getTotal(), page.getTotal(),
page.getPages(), page.getPages(),
machineProxyDtos machineProxyDtos
); );
} }
private QueryWrapper<MachineProxy> getMachineProxyQueryWrapper(MachineProxyDTO machineProxyDTO){ private QueryWrapper<MachineProxy> getMachineProxyQueryWrapper(MachineProxyDTO machineProxyDTO) {
QueryWrapper<MachineProxy> queryWrapper = new QueryWrapper<>(); QueryWrapper<MachineProxy> queryWrapper = new QueryWrapper<>();
if (machineProxyDTO.getHostIp() != null && !machineProxyDTO.getHostIp().isEmpty()) { if (machineProxyDTO.getHostIp() != null && !machineProxyDTO.getHostIp().isEmpty()) {
queryWrapper.eq("host_ip", machineProxyDTO.getHostIp()); queryWrapper.like("host_ip", machineProxyDTO.getHostIp());
} }
if (machineProxyDTO.getSshPort() != null && !machineProxyDTO.getSshPort().isEmpty()) { if (machineProxyDTO.getSshPort() != null && !machineProxyDTO.getSshPort().isEmpty()) {
queryWrapper.eq("ssh_port", machineProxyDTO.getSshPort()); queryWrapper.like("ssh_port", machineProxyDTO.getSshPort());
} }
if (machineProxyDTO.getUsername() != null && !machineProxyDTO.getUsername().isEmpty()) { if (machineProxyDTO.getUsername() != null && !machineProxyDTO.getUsername().isEmpty()) {
queryWrapper.eq("username", machineProxyDTO.getUsername()); queryWrapper.like("username", machineProxyDTO.getUsername());
} }
if (machineProxyDTO.getDescription() != null && !machineProxyDTO.getDescription().isEmpty()) { if (machineProxyDTO.getDescription() != null && !machineProxyDTO.getDescription().isEmpty()) {
queryWrapper.eq("description", machineProxyDTO.getDescription()); queryWrapper.like("description", machineProxyDTO.getDescription());
} }
if (machineProxyDTO.getStatus() != null && !machineProxyDTO.getStatus().isEmpty()) { if (machineProxyDTO.getStatus() != null && !machineProxyDTO.getStatus().isEmpty()) {
queryWrapper.eq("status_code", EnumUtils.getEnumByMessage(machineProxyDTO.getStatus(),MachineProxyStatus.class).getCode()); queryWrapper.like("status_code", EnumUtils.getEnumByMessage(machineProxyDTO.getStatus(), MachineProxyStatus.class).getCode());
} }
return queryWrapper; if (machineProxyDTO.getProxyType() != null && !machineProxyDTO.getProxyType().isEmpty()) {
queryWrapper.like("proxy_type_code", EnumUtils.getEnumByMessage(machineProxyDTO.getProxyType(), MachineProxyType.class).getCode());
}
return queryWrapper.orderByDesc("create_date");
} }
} }

View File

@ -17,23 +17,28 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Slf4j @Slf4j
@Service @Service
public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, MachineInfo> implements MachineInfoService { public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, MachineInfo> implements MachineInfoService {
int ENABLE=1; int ENABLE = 1;
int UN_ENABLE=0; int UN_ENABLE = 0;
@Resource @Resource
private MachineInfoMapper machineInfoMapper; private MachineInfoMapper machineInfoMapper;
@ -52,6 +57,7 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
* 机器名称 -> 会话ID * 机器名称 -> 会话ID
*/ */
private final Map<String, String> machineSessionMapping = new ConcurrentHashMap<>(); private final Map<String, String> machineSessionMapping = new ConcurrentHashMap<>();
@Override @Override
public boolean addMachineInfo(MachineInfoDto machineInfoDto) { public boolean addMachineInfo(MachineInfoDto machineInfoDto) {
if (machineInfoDto == null) { if (machineInfoDto == null) {
@ -67,8 +73,8 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
); );
machineInfo.setMachineInfoTypeCode( machineInfo.setMachineInfoTypeCode(
"Windows".equals(machineInfoDto.getMachineInfoType()) "Windows".equals(machineInfoDto.getMachineInfoType())
? MachineInfoType.WINDOWS.getCode() ? MachineInfoType.WINDOWS.getCode()
: MachineInfoType.Linux.getCode() : MachineInfoType.Linux.getCode()
); );
return this.save(machineInfo); return this.save(machineInfo);
@ -114,30 +120,35 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
); );
machineInfo.setMachineInfoTypeCode( machineInfo.setMachineInfoTypeCode(
"Windows".equals(machineInfoDto.getMachineInfoType()) "Windows".equals(machineInfoDto.getMachineInfoType())
? MachineInfoType.WINDOWS.getCode() ? MachineInfoType.WINDOWS.getCode()
: MachineInfoType.Linux.getCode() : MachineInfoType.Linux.getCode()
); );
return this.updateById(machineInfo); return this.updateById(machineInfo);
} }
@Override @Override
public boolean updateStatus(Long machineInfoId, String status) { public boolean updateStatus(MachineInfoDto machineInfoDto) {
UpdateWrapper<MachineInfo> updateWrapper = new UpdateWrapper<>(); UpdateWrapper<MachineInfo> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", machineInfoId).set("status_code", EnumUtils.getEnumByMessage(status, MachineInfoStatus.class).getCode()); updateWrapper.eq("id", machineInfoDto.getId()).set("status_code", EnumUtils.getEnumByMessage(machineInfoDto.getStatus(), MachineInfoStatus.class).getCode());
return this.update(updateWrapper); return this.update(updateWrapper);
} }
@Override @Override
public boolean bindingSecretKey(Long machineInfoId, Long secretKeyId) { public boolean bindingSecretKey(MachineInfoDto machineInfoDto) {
UpdateWrapper<MachineInfo> updateWrapper = new UpdateWrapper<>(); UpdateWrapper<MachineInfo> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", machineInfoId).set("secret_key_id", secretKeyId).set("authentication_type_code",2); updateWrapper.eq("id", machineInfoDto.getId()).set("secret_key_id", machineInfoDto.getSecretKeyId()).set("authentication_type_code", 2);
return this.update(updateWrapper); return this.update(updateWrapper);
} }
@Override @Override
public void deleteList(List<Long> machineInfoIds) { public void deleteList(String machineInfoIds) {
machineInfoMapper.selectBatchIds(machineInfoIds).forEach(machineInfo -> { List<Long> machineInfoIdList = Arrays.stream(machineInfoIds.split(","))
if (machineInfo.getStatusCode() == 1){ .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()); this.removeById(machineInfo.getId());
} }
}); });
@ -146,14 +157,14 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
@Override @Override
public void deleteMachineInfo(Long machineInfoId) { public void deleteMachineInfo(Long machineInfoId) {
MachineInfo machineInfo = this.getById(machineInfoId); MachineInfo machineInfo = this.getById(machineInfoId);
if (machineInfo.getStatusCode() == 1){ if (machineInfo.getStatusCode() == 1) {
this.removeById(machineInfoId); this.removeById(machineInfoId);
} }
} }
private QueryWrapper<MachineInfo> getMachineInfoQueryWrapper(MachineInfoDto machineInfoDto) { private QueryWrapper<MachineInfo> getMachineInfoQueryWrapper(MachineInfoDto machineInfoDto) {
QueryWrapper<MachineInfo> queryWrapper = new QueryWrapper<>(); QueryWrapper<MachineInfo> queryWrapper = new QueryWrapper<>();
if (machineInfoDto.getStatus() != null && !machineInfoDto.getStatus().isEmpty()){ if (machineInfoDto.getStatus() != null && !machineInfoDto.getStatus().isEmpty()) {
queryWrapper.eq("status_code", EnumUtils.getEnumByMessage(machineInfoDto.getStatus(), MachineInfoStatus.class).getCode()); queryWrapper.eq("status_code", EnumUtils.getEnumByMessage(machineInfoDto.getStatus(), MachineInfoStatus.class).getCode());
} }
if (machineInfoDto.getName() != null && !machineInfoDto.getName().isEmpty()) { if (machineInfoDto.getName() != null && !machineInfoDto.getName().isEmpty()) {
@ -168,15 +179,13 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
if (machineInfoDto.getDescription() != null && !machineInfoDto.getDescription().isEmpty()) { if (machineInfoDto.getDescription() != null && !machineInfoDto.getDescription().isEmpty()) {
queryWrapper.like("description", machineInfoDto.getDescription()); queryWrapper.like("description", machineInfoDto.getDescription());
} }
return queryWrapper; return queryWrapper.orderByDesc("create_date");
} }
@Override @Override
public boolean testConnection(MachineInfo machineInfo) { public boolean testConnection(MachineInfo machineInfo) {
if (machineInfo.getStatus().getCode()==UN_ENABLE) { if (machineInfo.getStatus().getCode() == UN_ENABLE) {
throw new RuntimeException("机器不可用"); throw new RuntimeException("机器不可用");
} }
log.info("测试机器连接: {}", machineInfo.getHostIp()); log.info("测试机器连接: {}", machineInfo.getHostIp());
@ -215,7 +224,7 @@ public class MachineinfoServiceImpl extends ServiceImpl<MachineInfoMapper, Machi
@Override @Override
public String connect(MachineInfo machineInfo) { public String connect(MachineInfo machineInfo) {
if (machineInfo.getStatus().getCode()==UN_ENABLE) { if (machineInfo.getStatus().getCode() == UN_ENABLE) {
throw new RuntimeException("机器不可用"); throw new RuntimeException("机器不可用");
} }
log.info("建立机器连接: {}", machineInfo.getHostIp()); log.info("建立机器连接: {}", machineInfo.getHostIp());