🔨 执行命令.
This commit is contained in:
@@ -7,6 +7,7 @@ import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||
import com.orion.ops.module.asset.define.operator.ExecOperatorType;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecCommandRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecInterruptRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ReExecCommandRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecCommandVO;
|
||||
import com.orion.ops.module.asset.service.ExecService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -41,10 +42,18 @@ public class ExecController {
|
||||
@PostMapping("/exec-command")
|
||||
@Operation(summary = "批量执行命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
|
||||
public ExecCommandVO execCommand(@RequestBody ExecCommandRequest request) {
|
||||
public ExecCommandVO execCommand(@Validated @RequestBody ExecCommandRequest request) {
|
||||
return execService.execCommand(request);
|
||||
}
|
||||
|
||||
@OperatorLog(ExecOperatorType.EXEC_COMMAND)
|
||||
@PostMapping("/re-exec-command")
|
||||
@Operation(summary = "重新执行命令")
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec:exec-command')")
|
||||
public ExecCommandVO reExecCommand(@Validated @RequestBody ReExecCommandRequest request) {
|
||||
return execService.reExecCommand(request.getLogId());
|
||||
}
|
||||
|
||||
@OperatorLog(ExecOperatorType.INTERRUPT_EXEC)
|
||||
@PutMapping("/interrupt")
|
||||
@Operation(summary = "中断执行命令")
|
||||
@@ -66,7 +75,6 @@ public class ExecController {
|
||||
}
|
||||
|
||||
// TODO tail log
|
||||
// TODO 重新执行
|
||||
// TODO 删除时 中断
|
||||
// TODO parameterSchema 存储
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import com.orion.ops.framework.mybatis.core.mapper.IMapper;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecHostLogDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 批量执行主机日志 Mapper 接口
|
||||
*
|
||||
@@ -14,4 +16,18 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper
|
||||
public interface ExecHostLogDAO extends IMapper<ExecHostLogDO> {
|
||||
|
||||
/**
|
||||
* 通过 logId 查询
|
||||
*
|
||||
* @param logId logId
|
||||
* @return rows
|
||||
*/
|
||||
default List<ExecHostLogDO> selectByLogId(Long logId) {
|
||||
return this.of()
|
||||
.createWrapper()
|
||||
.eq(ExecHostLogDO::getLogId, logId)
|
||||
.then()
|
||||
.list();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,9 +22,6 @@ import java.util.List;
|
||||
@Schema(name = "ExecCommandRequest", description = "批量执行命令 请求对象")
|
||||
public class ExecCommandRequest {
|
||||
|
||||
@Schema(description = "执行模板id")
|
||||
private Long templateId;
|
||||
|
||||
@Size(max = 128)
|
||||
@Schema(description = "执行描述")
|
||||
private String description;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.orion.ops.module.asset.entity.request.exec;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 重新执行命令 请求对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/3/11 11:46
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "ReExecCommandRequest", description = "重新执行命令 请求对象")
|
||||
public class ReExecCommandRequest {
|
||||
|
||||
@NonNull
|
||||
@Schema(description = "logId")
|
||||
private Long logId;
|
||||
|
||||
}
|
||||
@@ -20,6 +20,14 @@ public interface ExecService {
|
||||
*/
|
||||
ExecCommandVO execCommand(ExecCommandRequest request);
|
||||
|
||||
/**
|
||||
* 重新执行命令
|
||||
*
|
||||
* @param id id
|
||||
* @return result
|
||||
*/
|
||||
ExecCommandVO reExecCommand(Long id);
|
||||
|
||||
/**
|
||||
* 中断命令执行
|
||||
*
|
||||
|
||||
@@ -9,6 +9,9 @@ import com.orion.ops.module.asset.convert.ExecHostLogConvert;
|
||||
import com.orion.ops.module.asset.dao.ExecHostLogDAO;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecHostLogDO;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecHostLogVO;
|
||||
import com.orion.ops.module.asset.handler.host.exec.handler.IExecCommandHandler;
|
||||
import com.orion.ops.module.asset.handler.host.exec.handler.IExecTaskHandler;
|
||||
import com.orion.ops.module.asset.handler.host.exec.manager.ExecManager;
|
||||
import com.orion.ops.module.asset.service.ExecHostLogService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -16,6 +19,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 批量执行主机日志 服务实现类
|
||||
@@ -31,6 +35,9 @@ public class ExecHostLogServiceImpl implements ExecHostLogService {
|
||||
@Resource
|
||||
private ExecHostLogDAO execHostLogDAO;
|
||||
|
||||
@Resource
|
||||
private ExecManager execManager;
|
||||
|
||||
@Override
|
||||
public List<ExecHostLogVO> getExecHostLogList(Long logId) {
|
||||
return execHostLogDAO.of()
|
||||
@@ -65,6 +72,14 @@ public class ExecHostLogServiceImpl implements ExecHostLogService {
|
||||
// 检查数据是否存在
|
||||
ExecHostLogDO record = execHostLogDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 中断
|
||||
Optional.ofNullable(record.getLogId())
|
||||
.map(execManager::getTask)
|
||||
.map(IExecTaskHandler::getHandlers)
|
||||
.flatMap(s -> s.stream()
|
||||
.filter(h -> h.getHostId().equals(record.getHostId()))
|
||||
.findFirst())
|
||||
.ifPresent(IExecCommandHandler::interrupted);
|
||||
// 删除
|
||||
int effect = execHostLogDAO.deleteById(id);
|
||||
log.info("ExecHostLogService-deleteExecHostLogById id: {}, effect: {}", id, effect);
|
||||
|
||||
@@ -18,6 +18,8 @@ import com.orion.ops.module.asset.entity.request.exec.ExecLogQueryRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecHostLogVO;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecLogStatusVO;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecLogVO;
|
||||
import com.orion.ops.module.asset.handler.host.exec.handler.IExecTaskHandler;
|
||||
import com.orion.ops.module.asset.handler.host.exec.manager.ExecManager;
|
||||
import com.orion.ops.module.asset.service.ExecHostLogService;
|
||||
import com.orion.ops.module.asset.service.ExecLogService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -26,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -48,6 +51,9 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
@Resource
|
||||
private ExecHostLogService execHostLogService;
|
||||
|
||||
@Resource
|
||||
private ExecManager execManager;
|
||||
|
||||
@Override
|
||||
public DataGrid<ExecLogVO> getExecLogPage(ExecLogQueryRequest request) {
|
||||
// 条件
|
||||
@@ -74,6 +80,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
List<ExecHostLogVO> hostList = execHostLogDAO.of()
|
||||
.createWrapper()
|
||||
.select(ExecHostLogDO::getId,
|
||||
ExecHostLogDO::getLogId,
|
||||
ExecHostLogDO::getStatus,
|
||||
ExecHostLogDO::getStartTime,
|
||||
ExecHostLogDO::getFinishTime,
|
||||
@@ -101,6 +108,8 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
// 检查数据是否存在
|
||||
ExecLogDO record = execLogDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 中断命令执行
|
||||
this.interruptedTask(Lists.singleton(id));
|
||||
// 删除执行日志
|
||||
int effect = execLogDAO.deleteById(id);
|
||||
// 删除主机日志
|
||||
@@ -115,6 +124,8 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer deleteExecLogByIdList(List<Long> idList) {
|
||||
log.info("ExecLogService-deleteExecLogByIdList idList: {}", idList);
|
||||
// 中断命令执行
|
||||
this.interruptedTask(idList);
|
||||
// 删除执行日志
|
||||
int effect = execLogDAO.deleteBatchIds(idList);
|
||||
// 删除主机日志
|
||||
@@ -138,6 +149,8 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
.collect(Collectors.toList());
|
||||
int effect = 0;
|
||||
if (!idList.isEmpty()) {
|
||||
// 中断命令执行
|
||||
this.interruptedTask(idList);
|
||||
// 删除执行日志
|
||||
effect = execLogDAO.delete(wrapper);
|
||||
// 删除主机日志
|
||||
@@ -170,4 +183,16 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
.orderByDesc(ExecLogDO::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 中断任务
|
||||
*
|
||||
* @param idList idList
|
||||
*/
|
||||
private void interruptedTask(List<Long> idList) {
|
||||
idList.stream()
|
||||
.map(execManager::getTask)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(IExecTaskHandler::interrupted);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ import java.util.stream.Collectors;
|
||||
public class ExecServiceImpl implements ExecService {
|
||||
|
||||
private static final ReplacementFormatter FORMATTER = ReplacementFormatters.create("@{{ ", " }}")
|
||||
.noMatchStrategy(NoMatchStrategy.EMPTY);
|
||||
.noMatchStrategy(NoMatchStrategy.KEEP);
|
||||
|
||||
@Resource
|
||||
private FileClient logsFileClient;
|
||||
@@ -124,23 +124,10 @@ public class ExecServiceImpl implements ExecService {
|
||||
.build();
|
||||
}).collect(Collectors.toList());
|
||||
execHostLogDAO.insertBatch(execHostLogs);
|
||||
// 开始执行
|
||||
ExecCommandDTO exec = ExecCommandDTO.builder()
|
||||
.logId(execId)
|
||||
.timeout(request.getTimeout())
|
||||
.hosts(execHostLogs.stream()
|
||||
.map(s -> ExecCommandHostDTO.builder()
|
||||
.hostId(s.getHostId())
|
||||
.hostLogId(s.getId())
|
||||
.command(s.getCommand())
|
||||
.timeout(request.getTimeout())
|
||||
.logPath(s.getLogPath())
|
||||
.build())
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
ExecTaskExecutors.start(exec);
|
||||
// 操作日志
|
||||
OperatorLogs.add(OperatorLogs.ID, execId);
|
||||
// 开始执行
|
||||
this.startExec(execLog, execHostLogs);
|
||||
// 返回
|
||||
List<ExecCommandHostVO> hostResult = execHostLogs.stream()
|
||||
.map(s -> ExecCommandHostVO.builder()
|
||||
@@ -154,6 +141,29 @@ public class ExecServiceImpl implements ExecService {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecCommandVO reExecCommand(Long logId) {
|
||||
log.info("ExecService.reExecCommand start logId: {}", logId);
|
||||
// 获取执行记录
|
||||
ExecLogDO execLog = execLogDAO.selectById(logId);
|
||||
Valid.notNull(execLog, ErrorMessage.DATA_ABSENT);
|
||||
// 获取执行主机
|
||||
List<ExecHostLogDO> hostLogs = execHostLogDAO.selectByLogId(logId);
|
||||
Valid.notEmpty(hostLogs, ErrorMessage.DATA_ABSENT);
|
||||
List<Long> hostIdList = hostLogs.stream()
|
||||
.map(ExecHostLogDO::getHostId)
|
||||
.collect(Collectors.toList());
|
||||
// 调用执行方法
|
||||
ExecCommandRequest request = ExecCommandRequest.builder()
|
||||
.description(execLog.getDescription())
|
||||
.timeout(execLog.getTimeout())
|
||||
.command(execLog.getCommand())
|
||||
.parameter(hostLogs.get(0).getParameter())
|
||||
.hostIdList(hostIdList)
|
||||
.build();
|
||||
return this.execCommand(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void interruptExec(Long logId) {
|
||||
@@ -250,6 +260,29 @@ public class ExecServiceImpl implements ExecService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始执行命令
|
||||
*
|
||||
* @param execLog execLog
|
||||
* @param execHostLogs hostLogs
|
||||
*/
|
||||
private void startExec(ExecLogDO execLog, List<ExecHostLogDO> execHostLogs) {
|
||||
ExecCommandDTO exec = ExecCommandDTO.builder()
|
||||
.logId(execLog.getId())
|
||||
.timeout(execLog.getTimeout())
|
||||
.hosts(execHostLogs.stream()
|
||||
.map(s -> ExecCommandHostDTO.builder()
|
||||
.hostId(s.getHostId())
|
||||
.hostLogId(s.getId())
|
||||
.command(s.getCommand())
|
||||
.timeout(execLog.getTimeout())
|
||||
.logPath(s.getLogPath())
|
||||
.build())
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
ExecTaskExecutors.start(exec);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建日志路径
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user