refactor(接口定义): 优化本地下载jar

--story=1011108 --user=王孝刚 资源池加载插件直接从MinIO获取
https://www.tapd.cn/55049933/s/1331634
This commit is contained in:
wxg0103 2023-02-13 15:39:22 +08:00 committed by wxg0103
parent d0b468071b
commit fac9c3eda7
14 changed files with 79 additions and 87 deletions

View File

@ -4,11 +4,14 @@ import com.alibaba.excel.util.StringUtils;
import io.metersphere.commons.constants.ApiTestConstants;
import io.metersphere.commons.constants.ElementConstants;
import io.metersphere.commons.utils.JSON;
import io.metersphere.dto.ProjectJarConfig;
import io.metersphere.enums.JmxFileMetadataColumns;
import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
@ -16,6 +19,7 @@ import org.apache.jmeter.testelement.TestPlan;
import org.apache.jorphan.collections.HashTree;
import java.util.List;
import java.util.Map;
@Data
@EqualsAndHashCode(callSuper = true)
@ -28,6 +32,9 @@ public class MsTestPlan extends MsTestElement {
private boolean serializeThreadGroups = false;
// 资源池调用的时候需要的jar配置
private Map<String, List<ProjectJarConfig>> poolJarsMap;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, MsParameter msParameter) {
ParameterConfig config = (ParameterConfig) msParameter;
@ -50,6 +57,9 @@ public class MsTestPlan extends MsTestElement {
if (CollectionUtils.isNotEmpty(projectJarIds)) {
testPlan.setProperty(ApiTestConstants.JAR_PATH, JSON.toJSONString(projectJarIds));
}
if (MapUtils.isNotEmpty(poolJarsMap)) {
testPlan.setProperty(JmxFileMetadataColumns.JAR_PATH_CONFIG.name(), JSON.toJSONString(poolJarsMap));
}
testPlan.setUserDefinedVariables(new Arguments());
return testPlan;
}

View File

@ -28,6 +28,7 @@ import io.metersphere.commons.enums.ApiReportStatus;
import io.metersphere.commons.utils.*;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.ProjectJarConfig;
import io.metersphere.dto.ResultDTO;
import io.metersphere.environment.service.BaseEnvironmentService;
import io.metersphere.plugin.core.MsTestElement;
@ -131,14 +132,13 @@ public class ApiCaseSerialService {
if (caseWithBLOBs != null) {
HashTree jmeterHashTree = new HashTree();
MsTestPlan testPlan = new MsTestPlan();
if (!runRequest.getPool().isPool()) {
// 获取自定义JAR
String projectId = caseWithBLOBs.getProjectId();
testPlan.setProjectJarIds(NewDriverManager.getJars(new ArrayList<>() {{
this.add(projectId);
}}, runRequest.getPool()).keySet().stream().toList());
}
// 获取自定义JAR
String projectId = caseWithBLOBs.getProjectId();
Map<String, List<ProjectJarConfig>> jars = NewDriverManager.getJars(new ArrayList<>() {{
this.add(projectId);
}}, runRequest.getPool());
testPlan.setProjectJarIds(jars.keySet().stream().toList());
testPlan.setPoolJarsMap(jars);
testPlan.setHashTree(new LinkedList<>());
MsThreadGroup group = new MsThreadGroup();
group.setLabel(caseWithBLOBs.getName());

View File

@ -14,6 +14,7 @@ import io.metersphere.dto.ProjectJarConfig;
import io.metersphere.jmeter.ProjectClassLoader;
import io.metersphere.metadata.service.FileMetadataService;
import io.metersphere.utils.JarConfigUtils;
import io.metersphere.utils.LocalPathUtil;
import io.metersphere.vo.BooleanPool;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
@ -70,7 +71,7 @@ public class NewDriverManager {
byte[] bytes = new byte[0];
// 兼容历史数据
bytes = fileMetadataService.getContent(s.getId());
ApiFileUtil.createFile(StringUtils.join(ApiFileUtil.LOCAL_JAR,
ApiFileUtil.createFile(StringUtils.join(LocalPathUtil.JAR_PATH,
File.separator,
key,
File.separator,

View File

@ -1,6 +1,5 @@
package io.metersphere.commons.config;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.utils.LocalPathUtil;
import io.metersphere.utils.TemporaryFileUtil;
import org.springframework.context.annotation.Bean;
@ -8,13 +7,14 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class UtilsConfig {
static {
LocalPathUtil.JAR_PATH += LocalPathUtil.MS;
LocalPathUtil.PLUGIN_PATH += LocalPathUtil.MS;
}
@Bean
public TemporaryFileUtil temporaryFileUtil() {
return new TemporaryFileUtil(TemporaryFileUtil.MS_FILE_FOLDER);
}
@Bean
public void localPathUtil() {
LocalPathUtil.prePath = FileUtils.LOCAL_JAR;
}
}

View File

@ -10,6 +10,7 @@ import io.metersphere.enums.JmxFileMetadataColumns;
import io.metersphere.metadata.service.FileManagerService;
import io.metersphere.metadata.service.FileMetadataService;
import io.metersphere.metadata.vo.FileRequest;
import io.metersphere.utils.LocalPathUtil;
import io.metersphere.utils.LoggerUtil;
import io.metersphere.utils.TemporaryFileUtil;
import org.apache.commons.collections.CollectionUtils;
@ -36,7 +37,7 @@ public class ApiFileUtil extends FileUtils {
infoDTOS.forEach(item -> {
value.forEach(config -> {
if (StringUtils.equals(item.getId(), config.getId())) {
createFile(StringUtils.join(ApiFileUtil.LOCAL_JAR,
createFile(StringUtils.join(LocalPathUtil.JAR_PATH,
File.separator,
key,
File.separator,

View File

@ -13,10 +13,7 @@ import io.metersphere.base.mapper.TestResourcePoolMapper;
import io.metersphere.commons.constants.ElementConstants;
import io.metersphere.commons.constants.ResourcePoolTypeEnum;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.dto.JmeterRunRequestDTO;
import io.metersphere.dto.ResultDTO;
import io.metersphere.dto.RunModeConfigDTO;
import io.metersphere.dto.*;
import io.metersphere.environment.service.BaseEnvGroupProjectService;
import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.service.ApiExecutionQueueService;
@ -112,18 +109,6 @@ public class GenerateHashTreeUtil {
HashTree jmeterHashTree = new HashTree();
MsTestPlan testPlan = new MsTestPlan();
if (!runRequest.getPool().isPool()) {
// 获取自定义JAR
String projectId = item.getProjectId();
List<String> projectIds = new ArrayList<>();
projectIds.add(projectId);
if (MapUtils.isNotEmpty(planEnvMap)) {
planEnvMap.forEach((k, v) -> {
projectIds.add(k);
});
}
testPlan.setProjectJarIds(NewDriverManager.getJars(projectIds, runRequest.getPool()).keySet().stream().toList());
}
testPlan.setHashTree(new LinkedList<>());
try {
MsThreadGroup group = new MsThreadGroup();
@ -139,6 +124,27 @@ public class GenerateHashTreeUtil {
} else {
setScenarioEnv(scenario, item);
}
// 获取自定义JAR
String currentProjectId = item.getProjectId();
List<String> projectIds = new ArrayList<>();
projectIds.add(currentProjectId);
if (MapUtils.isNotEmpty(planEnvMap)) {
planEnvMap.forEach((projectId, env) -> {
if (!projectIds.contains(projectId)) {
projectIds.add(projectId);
}
});
}
if (MapUtils.isNotEmpty(scenario.getEnvironmentMap())) {
scenario.getEnvironmentMap().forEach((projectId, env) -> {
if (!projectIds.contains(projectId)) {
projectIds.add(projectId);
}
});
}
Map<String, List<ProjectJarConfig>> jarsMap = NewDriverManager.getJars(projectIds, runRequest.getPool());
testPlan.setProjectJarIds(jarsMap.keySet().stream().toList());
testPlan.setPoolJarsMap(jarsMap);
String data = definition;
// 失败重试
if (runRequest.isRetryEnable() && runRequest.getRetryNum() > 0) {

View File

@ -31,15 +31,6 @@ public class ApiJMeterFileController {
return JMeterThreadUtils.stop(name);
}
@GetMapping("download/jar")
public ResponseEntity<byte[]> downloadJmeterFiles() {
byte[] bytes = apiJmeterFileService.downloadJmeterJar();
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + UUID.randomUUID().toString() + ".zip\"")
.body(bytes);
}
@PostMapping("download/jar")
public ResponseEntity<byte[]> downloadJmeterFiles(@RequestBody Map<String, List<ProjectJarConfig>> jarConfigs) {
byte[] bytes = apiJmeterFileService.downloadJmeterJar(jarConfigs);

View File

@ -21,6 +21,7 @@ import io.metersphere.environment.service.BaseEnvGroupProjectService;
import io.metersphere.metadata.service.FileMetadataService;
import io.metersphere.request.BodyFile;
import io.metersphere.utils.LoggerUtil;
import io.metersphere.vo.BooleanPool;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
@ -71,6 +72,9 @@ public class ApiJMeterFileService {
JmeterRunRequestDTO runRequest = new JmeterRunRequestDTO(remoteTestId, reportId, runMode);
runRequest.setReportType(reportType);
runRequest.setQueueId(queueId);
BooleanPool booleanPool = new BooleanPool();
booleanPool.setK8s(true);
runRequest.setPool(booleanPool);
ApiScenarioWithBLOBs scenario = null;
if (StringUtils.equalsAny(runMode, ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.JENKINS_SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) {
@ -140,19 +144,6 @@ public class ApiJMeterFileService {
return zipFilesToByteArray((reportId + "_" + remoteTestId), reportId, hashTree);
}
public byte[] downloadJmeterJar() {
Map<String, byte[]> files = new HashMap<>();
// 获取JAR
Map<String, byte[]> jarFiles = this.getJar(null);
if (!MapUtils.isEmpty(jarFiles)) {
for (String k : jarFiles.keySet()) {
byte[] v = jarFiles.get(k);
files.put(k, v);
}
}
return listBytesToZip(files);
}
public byte[] downloadJmeterJar(Map<String, List<ProjectJarConfig>> map) {
Map<String, byte[]> files = new HashMap<>();
if (MapUtils.isNotEmpty(map)) {
@ -180,7 +171,7 @@ public class ApiJMeterFileService {
Map<String, byte[]> files = new HashMap<>();
if (CollectionUtils.isNotEmpty(pluginIds)) {
// 获取JAR
Map<String, byte[]> jarFiles = this.getPlugJar(pluginIds);
Map<String, byte[]> jarFiles = this.getPluginJar(pluginIds);
if (MapUtils.isNotEmpty(jarFiles)) {
for (String k : jarFiles.keySet()) {
byte[] v = jarFiles.get(k);
@ -191,30 +182,7 @@ public class ApiJMeterFileService {
return listBytesToZip(files);
}
private Map<String, byte[]> getJar(String projectId) {
Map<String, byte[]> jarFiles = new LinkedHashMap<>();
FileMetadataService jarConfigService = CommonBeanFactory.getBean(FileMetadataService.class);
if (jarConfigService != null) {
List<String> files = jarConfigService.getJar(new ArrayList<>() {{
this.add(projectId);
}});
files.forEach(path -> {
File file = new File(path);
if (file.isDirectory() && !path.endsWith("/")) {
file = new File(path + "/");
}
byte[] fileByte = FileUtils.fileToByte(file);
if (fileByte != null) {
jarFiles.put(file.getName(), fileByte);
}
});
return jarFiles;
} else {
return new HashMap<>();
}
}
public Map<String, byte[]> getPlugJar(List<String> pluginIds) {
public Map<String, byte[]> getPluginJar(List<String> pluginIds) {
Map<String, byte[]> jarFiles = new LinkedHashMap<>();
PluginExample example = new PluginExample();
example.createCriteria().andPluginIdIn(pluginIds).andScenarioNotEqualTo(PluginScenario.platform.name());

View File

@ -5,5 +5,6 @@ public enum JmxFileMetadataColumns {
REF_FILE_UPDATE_TIME,
REF_FILE_PROJECT_ID,
REF_FILE_ATTACH_INFO,
REF_FILE_NAME
REF_FILE_NAME,
JAR_PATH_CONFIG,
}

View File

@ -20,7 +20,7 @@ public class ProjectClassLoader {
public static void initClassLoader(List<String> projectIds) {
// 读取所有JAR路径
for (String projectId : projectIds) {
List<String> jarPaths = JarConfigUtils.walk(LocalPathUtil.prePath + File.separator + projectId);
List<String> jarPaths = JarConfigUtils.walk(LocalPathUtil.JAR_PATH + File.separator + projectId);
if (CollectionUtils.isNotEmpty(jarPaths)) {
LoggerUtil.info("加载JAR-PATH:" + JsonUtils.toJSONString(jarPaths), projectId);
// 初始化类加载器
@ -48,7 +48,7 @@ public class ProjectClassLoader {
public static void initClassLoader() {
// 读取所有JAR路径
List<String> projectIds = JarConfigUtils.getFileNames(LocalPathUtil.prePath + File.separator);
List<String> projectIds = JarConfigUtils.getFileNames(LocalPathUtil.JAR_PATH + File.separator);
LoggerUtil.info("初始化所有JAR" + JsonUtils.toJSONString(projectIds));
if (CollectionUtils.isNotEmpty(projectIds)) {
initClassLoader(projectIds);

View File

@ -31,7 +31,7 @@ public class CustomizeFunctionUtil {
if (StringUtils.isNotEmpty(pathStr) && context != null) {
List<String> projectIds = JsonUtils.parseObject(pathStr, List.class);
LoggerUtil.info("加载JAR-PROJECT-ID:" + projectIds, testPlan.getName());
LoggerUtil.info("PRE-PATH:" + LocalPathUtil.prePath, testPlan.getName());
LoggerUtil.info("PRE-PATH:" + LocalPathUtil.JAR_PATH, testPlan.getName());
if (CollectionUtils.isNotEmpty(projectIds)) {
// 读取所有JAR路径
List<String> jarPaths = JarConfigUtils.findPathByProjectIds(projectIds);

View File

@ -20,7 +20,7 @@ import java.util.stream.Stream;
public class JarConfigUtils {
public static Map<String, List<ProjectJarConfig>> getJarConfigs(List<String> projectIds, Map<String, List<ProjectJarConfig>> jarConfigMap) {
String localPath = LocalPathUtil.prePath;
String localPath = LocalPathUtil.JAR_PATH;
Map<String, List<ProjectJarConfig>> jarConfigsMap = new HashMap<>();
projectIds.forEach(item -> {
List<ProjectJarConfig> jarConfigs = new ArrayList<>();
@ -109,7 +109,7 @@ public class JarConfigUtils {
List<String> jarPaths = new ArrayList<>();
if (CollectionUtils.isNotEmpty(projectIds)) {
projectIds.forEach(item -> {
jarPaths.addAll(walk(LocalPathUtil.prePath + File.separator + item));
jarPaths.addAll(walk(LocalPathUtil.JAR_PATH + File.separator + item));
});
}
return jarPaths;

View File

@ -1,5 +1,20 @@
package io.metersphere.utils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
public class LocalPathUtil {
public static String prePath;
public static final String NODE = "node";
public static final String MS = "ms";
public static final String PRE_PATH = File.separator + "opt"
+ File.separator + "metersphere"
+ File.separator + "data"
+ File.separator + "api-folder"
+ File.separator;
public static String JAR_PATH =
StringUtils.join(PRE_PATH, "jar", File.separator);
public static String PLUGIN_PATH = StringUtils.join(PRE_PATH, "plugin", File.separator);
}

View File

@ -33,7 +33,6 @@ public class FileUtils {
public static final String UI_IMAGE_DIR = "/opt/metersphere/data/image/ui/screenshots";
public static final String ATTACHMENT_DIR = "/opt/metersphere/data/attachment";
public static final String ATTACHMENT_TMP_DIR = "/opt/metersphere/data/attachment/tmp";
public static final String LOCAL_JAR = "/opt/metersphere/data/local-jar/jar";
public static void validateFileName(String fileName) {
if (StringUtils.isNotEmpty(fileName) && StringUtils.contains(fileName, "." + File.separator)) {