feat(接口测试): 测试计划支持禁用本地执行

--story=1009842 --user=赵勇 接口测试支持禁用本地执行 https://www.tapd.cn/55049933/s/1291450
This commit is contained in:
fit2-zhao 2022-11-16 14:30:47 +08:00 committed by fit2-zhao
parent 0b8d80f49d
commit 61b82c28fd
10 changed files with 49 additions and 43 deletions

View File

@ -23,6 +23,7 @@ import io.metersphere.service.BaseProjectApplicationService;
import io.metersphere.service.RemakeReportService;
import io.metersphere.service.SystemParameterService;
import io.metersphere.utils.LoggerUtil;
import io.metersphere.xpack.api.service.ApiPoolDebugService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
@ -58,11 +59,14 @@ public class JMeterService {
private SystemParameterService systemParameterService;
@Resource
private BaseProjectApplicationService projectApplicationService;
@Resource
private RemakeReportService remakeReportService;
@Resource
private ExecThreadPoolExecutor execThreadPoolExecutor;
@PostConstruct
private void init() {
String JMETER_HOME = getJmeterHome();
String JMETER_PROPERTIES = JMETER_HOME + "/bin/jmeter.properties";
JMeterUtils.loadJMeterProperties(JMETER_PROPERTIES);
JMeterUtils.setJMeterHome(JMETER_HOME);
@ -150,8 +154,7 @@ public class JMeterService {
final Engine engine = EngineFactory.createApiEngine(request);
engine.start();
} catch (Exception e) {
RemakeReportService apiScenarioReportService = CommonBeanFactory.getBean(RemakeReportService.class);
apiScenarioReportService.testEnded(request, e.getMessage());
remakeReportService.testEnded(request, e.getMessage());
LoggerUtil.error("调用K8S执行请求[ " + request.getTestId() + " ]失败:", request.getReportId(), e);
}
} else if ((MapUtils.isNotEmpty(request.getExtendedParameters())
@ -166,34 +169,15 @@ public class JMeterService {
private synchronized void nodeDebug(JmeterRunRequestDTO request) {
try {
if (request.isDebug() && !StringUtils.equalsAny(request.getRunMode(), ApiRunMode.DEFINITION.name())) {
request.getExtendedParameters().put(ExtendedParameter.SAVE_RESULT, true);
} else if (!request.isDebug()) {
request.getExtendedParameters().put(ExtendedParameter.SAVE_RESULT, true);
}
List<TestResource> resources = GenerateHashTreeUtil.setPoolResource(request.getPoolId());
String uri = null;
int index = (int) (Math.random() * resources.size());
String configuration = resources.get(index).getConfiguration();
if (StringUtils.isNotEmpty(configuration)) {
NodeDTO node = com.alibaba.fastjson.JSON.parseObject(configuration, NodeDTO.class);
uri = String.format(BASE_URL + "/jmeter/debug", node.getIp(), node.getPort());
}
if (StringUtils.isEmpty(uri)) {
LoggerUtil.info("未获取到资源池,请检查配置【系统设置-系统-测试资源池】", request.getReportId());
MSException.throwException("调用资源池执行失败,请检查资源池是否配置正常");
}
request.getExtendedParameters().put(ExtendedParameter.JMX, new MsTestPlan().getJmx(request.getHashTree()));
request.setHashTree(null);
LoggerUtil.info("开始发送请求【 " + request.getTestId() + " 】到 " + uri + " 节点执行", request.getReportId());
ResponseEntity<String> result = restTemplate.postForEntity(uri, request, String.class);
if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) {
LoggerUtil.error("发送请求[ " + request.getTestId() + " ] 到" + uri + " 节点执行失败", request.getReportId());
LoggerUtil.info(result);
MSException.throwException("调用资源池执行失败,请检查资源池是否配置正常");
ApiPoolDebugService apiPoolDebugService = CommonBeanFactory.getBean(ApiPoolDebugService.class);
if (apiPoolDebugService != null) {
List<TestResource> resources = GenerateHashTreeUtil.setPoolResource(request.getPoolId());
request.getExtendedParameters().put(ExtendedParameter.JMX, new MsTestPlan().getJmx(request.getHashTree()));
request.setHashTree(null);
apiPoolDebugService.run(request, resources);
}
} catch (Exception e) {
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
LoggerUtil.error(e);
remakeReportService.remake(request);
LoggerUtil.error("发送请求[ " + request.getTestId() + " ] 执行失败,进行数据回滚:", request.getReportId(), e);
MSException.throwException("调用资源池执行失败,请检查资源池是否配置正常");
@ -212,7 +196,6 @@ public class JMeterService {
}
if (config == null) {
LoggerUtil.info("未获取到资源池,请检查配置【系统设置-系统-测试资源池】", request.getReportId());
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(request);
return;
}
@ -221,13 +204,11 @@ public class JMeterService {
LoggerUtil.info("开始发送请求【 " + request.getTestId() + " 】到 " + config.getUrl() + " 节点执行", request.getReportId());
ResponseEntity<String> result = restTemplate.postForEntity(config.getUrl(), request, String.class);
if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) {
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(request);
LoggerUtil.error("发送请求[ " + request.getTestId() + " ] 到" + config.getUrl() + " 节点执行失败", request.getReportId());
LoggerUtil.info(result.getBody());
}
} catch (Exception e) {
RemakeReportService remakeReportService = CommonBeanFactory.getBean(RemakeReportService.class);
remakeReportService.remake(request);
LoggerUtil.error("发送请求[ " + request.getTestId() + " ] 执行失败,进行数据回滚:", request.getReportId(), e);
}
@ -240,7 +221,7 @@ public class JMeterService {
} else if (request.getHashTree() != null) {
//解析hashTree是否含有文件库文件
HashTreeUtil.initRepositoryFiles(request);
CommonBeanFactory.getBean(ExecThreadPoolExecutor.class).addTask(request);
execThreadPoolExecutor.addTask(request);
}
}
@ -275,7 +256,8 @@ public class JMeterService {
public void verifyPool(String projectId, RunModeConfigDTO runConfig) {
// 检查是否禁用了本地执行
if (runConfig != null && StringUtils.isEmpty(runConfig.getResourcePoolId())) {
if (runConfig != null && StringUtils.isEmpty(runConfig.getResourcePoolId())
&& CommonBeanFactory.getBean(ApiPoolDebugService.class) != null) {
BaseSystemConfigDTO configDTO = systemParameterService.getBaseInfo();
if (StringUtils.equals(configDTO.getRunMode(), POOL)) {
ProjectConfig config = projectApplicationService.getProjectConfig(projectId);

View File

@ -1,9 +1,9 @@
package io.metersphere.api.jmeter;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.metersphere.api.dto.MsgDTO;
import io.metersphere.commons.constants.KafkaTopicConstants;
import io.metersphere.commons.utils.JSONUtil;
import io.metersphere.commons.utils.NamedThreadFactory;
import io.metersphere.commons.utils.WebSocketUtil;
import io.metersphere.service.ApiExecutionQueueService;
@ -74,7 +74,7 @@ public class MsKafkaListener {
try {
LoggerUtil.info("接收到执行结果:", record.key());
if (ObjectUtils.isNotEmpty(record.value()) && WebSocketUtil.has(record.key().toString())) {
MsgDTO dto = JSON.parseObject(record.value(), MsgDTO.class);
MsgDTO dto = JSONUtil.parseObject(record.value(), MsgDTO.class);
WebSocketUtil.sendMessageSingle(dto);
}
} catch (Exception e) {

View File

@ -95,6 +95,7 @@ import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
import {getSystemBaseSetting} from "metersphere-frontend/src/api/system";
import EnvSelectPopover from "@/business/automation/scenario/EnvSelectPopover";
import {getApiCaseEnvironments} from "@/api/api-test-case";
import {hasLicense} from "metersphere-frontend/src/utils/permission";
export default {
name: "ApiRunMode",
@ -149,7 +150,9 @@ export default {
this.runModeVisible = true;
this.getResourcePools();
this.getWsProjects();
this.query();
if(hasLicense()) {
this.query();
}
this.showPopover();
this.runConfig.environmentType = ENV_TYPE.JSON;
},

View File

@ -109,6 +109,7 @@ import EnvPopover from "@/business/automation/scenario/EnvPopover";
import {getMaintainer, getOwnerProjects, getProjectConfig} from "@/api/project";
import {getTestResourcePools} from "@/api/test-resource-pool";
import {getSystemBaseSetting} from "metersphere-frontend/src/api/system";
import {hasLicense} from "metersphere-frontend/src/utils/permission";
function defaultCustomValidate() {
return {pass: true};
@ -317,7 +318,9 @@ export default {
this.activeName = 'first';
this.getResourcePools();
this.getWsProjects();
this.query();
if(hasLicense()) {
this.query();
}
this.runConfig.environmentType = ENV_TYPE.JSON;
},
findSchedule() {

View File

@ -0,0 +1,10 @@
package io.metersphere.xpack.api.service;
import io.metersphere.base.domain.TestResource;
import io.metersphere.dto.JmeterRunRequestDTO;
import java.util.List;
public interface ApiPoolDebugService {
public void run(JmeterRunRequestDTO request, List<TestResource> resources);
}

View File

@ -97,7 +97,7 @@
<!-- 接口测试资源池 -->
<app-manage-item :title="$t('pj.api_run_pool_title')" :prepend-span="8" :middle-span="12"
:append-span="4" v-if="isPool">
:append-span="4" v-if="isPool && isXpack">
<template #middle>
<el-select v-model="config.resourcePoolId"
size="mini"

View File

@ -19,7 +19,7 @@
<el-input v-model="formInline.seleniumDockerUrl" :placeholder="$t('system_config.selenium_docker.url_tip')"/>
<i>({{ $t('commons.examples') }}:http://localhost:4444)</i>
</el-form-item>
<el-form-item :label="$t('system.api_default_run')" prop="seleniumDockerUrl">
<el-form-item :label="$t('system.api_default_run')" prop="runMode" v-if="hasLicense()">
<el-switch active-value="LOCAL" inactive-value="POOL" v-model="formInline.runMode" @change="modeChange"/>
</el-form-item>
</el-col>
@ -38,6 +38,7 @@
<script>
import {getSystemBaseSetting, saveSystemBaseSetting} from "../../../api/system";
import {hasLicense} from 'metersphere-frontend/src/utils/permission';
export default {
name: "BaseSetting",
@ -76,6 +77,7 @@ export default {
this.query()
},
methods: {
hasLicense,
query() {
this.loading = getSystemBaseSetting().then(res => {
if(!res.data.runMode) {

View File

@ -281,7 +281,9 @@ export default {
this.testType = testType;
this.getResourcePools();
this.getWsProjects();
this.query();
if(hasLicense()) {
this.query();
}
},
query() {
this.loading = true;

View File

@ -292,7 +292,9 @@ export default {
this.getResourcePools();
this.getWsProjects();
this.showPopover();
this.query();
if(hasLicense()) {
this.query();
}
},
query() {
this.loading = true;

View File

@ -274,7 +274,9 @@ export default {
this.testType = testType;
this.getResourcePools();
this.getWsProjects();
this.query();
if(hasLicense()) {
this.query();
}
},
query() {
this.loading = true;