升级任务
This commit is contained in:
parent
57639e78a1
commit
2f81beb0d8
@ -1,6 +1,10 @@
|
||||
spring:
|
||||
application:
|
||||
name: tms-framework
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 104857600
|
||||
max-request-size: 104857600
|
||||
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
@ -11,6 +11,7 @@ import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.multipart.MaxUploadSizeExceededException;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
@ -45,6 +46,12 @@ public class GlobalExceptionHandler {
|
||||
return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), ex.getMessage()).withPath(request.getRequestURI());
|
||||
}
|
||||
|
||||
@ExceptionHandler(MaxUploadSizeExceededException.class)
|
||||
public ApiResponse<Void> handleMaxUploadSizeExceeded(MaxUploadSizeExceededException ex, HttpServletRequest request) {
|
||||
return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), "upload file size exceeds limit")
|
||||
.withPath(request.getRequestURI());
|
||||
}
|
||||
|
||||
@ExceptionHandler(PcieCryptoException.class)
|
||||
public ApiResponse<Void> handleCryptoCardException(PcieCryptoException ex, HttpServletRequest request) {
|
||||
return ApiResponse.fail(ErrorCode.CRYPTO_CARD_ERROR.getCode(), ex.getMessage())
|
||||
|
||||
@ -15,6 +15,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -26,17 +27,13 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "离线升级管理", description = "离线升级包上传、预检、任务创建、执行和升级记录查询接口")
|
||||
public class UpgradeController {
|
||||
|
||||
private final UpgradeService upgradeService;
|
||||
private final FileService fileService;
|
||||
|
||||
public UpgradeController(UpgradeService upgradeService, FileService fileService) {
|
||||
this.upgradeService = upgradeService;
|
||||
this.fileService = fileService;
|
||||
}
|
||||
|
||||
@PostMapping("/upgrade-packages")
|
||||
@Operation(summary = "上传离线升级包", description = "上传离线升级包,返回 fileId 供升级预检和任务创建使用。")
|
||||
public ApiResponse<FileUploadResponse> uploadPackage(
|
||||
|
||||
@ -98,8 +98,9 @@ public class UpgradeTaskRunner {
|
||||
}
|
||||
|
||||
DeviceSoftwareVersionEntity versionEntity = new DeviceSoftwareVersionEntity();
|
||||
versionEntity.setComponentCode(task.getTaskType());
|
||||
versionEntity.setComponentName(componentName(task.getTaskType()));
|
||||
String componentCode = componentCode(task.getTaskType());
|
||||
versionEntity.setComponentCode(componentCode);
|
||||
versionEntity.setComponentName(componentName(componentCode));
|
||||
versionEntity.setCurrentVersion(task.getTargetVersion());
|
||||
versionEntity.setSourceType("UPGRADE");
|
||||
versionEntity.setDetectedAt(LocalDateTime.now());
|
||||
@ -211,12 +212,18 @@ public class UpgradeTaskRunner {
|
||||
private String componentName(String componentCode) {
|
||||
return switch (trim(componentCode)) {
|
||||
case "TMS" -> "设备管理软件";
|
||||
case "RECEIVER" -> "标准收发器";
|
||||
case "FIRMWARE" -> "固件";
|
||||
case "APP" -> "标准收发器";
|
||||
default -> componentCode;
|
||||
};
|
||||
}
|
||||
|
||||
private String componentCode(String taskType) {
|
||||
return switch (trim(taskType)) {
|
||||
case "RECEIVER" -> "APP";
|
||||
default -> trim(taskType);
|
||||
};
|
||||
}
|
||||
|
||||
private String trim(String value) {
|
||||
return value == null ? "" : value.trim();
|
||||
}
|
||||
|
||||
@ -2,6 +2,11 @@ spring:
|
||||
application:
|
||||
# Spring 应用名;用于日志、注册中心标识等。
|
||||
name: tms-framework
|
||||
servlet:
|
||||
multipart:
|
||||
# Spring/Tomcat multipart 解析上限;必须不小于业务上传上限,否则请求会在进入 Controller 前被拒绝。
|
||||
max-file-size: ${TMS_FILE_STORAGE_MAX_FILE_SIZE_BYTES:104857600}
|
||||
max-request-size: ${TMS_FILE_STORAGE_MAX_FILE_SIZE_BYTES:104857600}
|
||||
profiles:
|
||||
# 默认激活环境;可通过 --spring.profiles.active=prod 覆盖。
|
||||
active: dev
|
||||
@ -173,7 +178,7 @@ tms:
|
||||
# 升级任务统一日志目录。
|
||||
log-dir: ${TMS_UPGRADE_LOG_DIR:/home/tms/tmp/tms-upgrade-logs}
|
||||
# 升级包验签使用的公钥 PEM 文件路径;为空时升级预检会拒绝通过。
|
||||
signature-public-key-pem-path: ${TMS_UPGRADE_SIGNATURE_PUBLIC_KEY_PEM_PATH:}
|
||||
signature-public-key-pem-path: ${TMS_UPGRADE_SIGNATURE_PUBLIC_KEY_PEM_PATH:/home/tms/cert/public_key.pem}
|
||||
mk:
|
||||
init-identify:
|
||||
# SDFE_InitIdentify 旧 PIN(Base64 编码);主密钥初始化接口会读取该值。
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
package com.cisd.tms.common.exception;
|
||||
|
||||
import com.cisd.tms.common.api.ApiResponse;
|
||||
import com.cisd.tms.common.enums.ErrorCode;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.multipart.MaxUploadSizeExceededException;
|
||||
|
||||
class GlobalExceptionHandlerTest {
|
||||
|
||||
@Test
|
||||
void shouldHandleMultipartMaxUploadSizeExceededAsValidationFailure() {
|
||||
GlobalExceptionHandler handler = new GlobalExceptionHandler();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/api/v1/upgrade-packages");
|
||||
|
||||
ApiResponse<Void> response = handler.handleMaxUploadSizeExceeded(
|
||||
new MaxUploadSizeExceededException(104857600),
|
||||
request
|
||||
);
|
||||
|
||||
Assertions.assertFalse(response.isSuccess());
|
||||
Assertions.assertEquals(ErrorCode.VALIDATE_FAILED.getCode(), response.getCode());
|
||||
Assertions.assertEquals("upload file size exceeds limit", response.getMsg());
|
||||
Assertions.assertEquals("/api/v1/upgrade-packages", response.getPath());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.cisd.tms.config;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.env.YamlPropertySourceLoader;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
|
||||
class MultipartUploadConfigurationTest {
|
||||
|
||||
@Test
|
||||
void shouldConfigureSpringMultipartLimitsForLargeUpgradePackages() throws Exception {
|
||||
FileSystemResource resource = new FileSystemResource(Path.of("src/main/resources/application.yml"));
|
||||
List<PropertySource<?>> propertySources = new YamlPropertySourceLoader().load("application", resource);
|
||||
|
||||
Object maxFileSize = findProperty(propertySources, "spring.servlet.multipart.max-file-size");
|
||||
Object maxRequestSize = findProperty(propertySources, "spring.servlet.multipart.max-request-size");
|
||||
|
||||
Assertions.assertEquals("${TMS_FILE_STORAGE_MAX_FILE_SIZE_BYTES:104857600}", maxFileSize);
|
||||
Assertions.assertEquals("${TMS_FILE_STORAGE_MAX_FILE_SIZE_BYTES:104857600}", maxRequestSize);
|
||||
}
|
||||
|
||||
private Object findProperty(List<PropertySource<?>> propertySources, String name) {
|
||||
return propertySources.stream()
|
||||
.filter(source -> source.containsProperty(name))
|
||||
.findFirst()
|
||||
.map(source -> source.getProperty(name))
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
@ -56,6 +56,32 @@ class UpgradeTaskRunnerTest {
|
||||
Assertions.assertTrue(log.indexOf("execute") < log.indexOf("verify"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateAppSoftwareVersionWhenReceiverUpgradeSucceeds() throws Exception {
|
||||
Path tempDir = Files.createTempDirectory("upgrade-runner-test");
|
||||
FileRecordEntity fileRecord = buildPackage(tempDir, false, "#!/bin/sh\necho execute\nexit 0\n", false);
|
||||
InMemoryFileRecordRepository fileRepository = new InMemoryFileRecordRepository();
|
||||
fileRepository.save(fileRecord);
|
||||
InMemoryUpgradeTaskRepository taskRepository = new InMemoryUpgradeTaskRepository();
|
||||
InMemoryDeviceSoftwareVersionRepository versionRepository = new InMemoryDeviceSoftwareVersionRepository();
|
||||
|
||||
UpgradeTaskRunner runner = new UpgradeTaskRunner(
|
||||
taskRepository,
|
||||
fileRepository,
|
||||
versionRepository,
|
||||
stagingService(tempDir.resolve("staging"), tempDir.resolve("logs")),
|
||||
properties(tempDir.resolve("staging"), tempDir.resolve("logs")),
|
||||
objectMapper
|
||||
);
|
||||
|
||||
runner.run(task("UPG-001-R", fileRecord.getFileId(), "RECEIVER", "V1.4.0"));
|
||||
|
||||
Assertions.assertEquals("SUCCESS", taskRepository.status);
|
||||
Assertions.assertNull(versionRepository.store.get("RECEIVER"));
|
||||
Assertions.assertEquals("V1.4.0", versionRepository.store.get("APP").getCurrentVersion());
|
||||
Assertions.assertEquals("标准收发器", versionRepository.store.get("APP").getComponentName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMarkTaskFailedWhenExecuteScriptFails() throws Exception {
|
||||
Path tempDir = Files.createTempDirectory("upgrade-runner-test");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user