feat(接口测试): 支持 k8s 执行

This commit is contained in:
fit2-zhao 2021-06-16 18:18:38 +08:00 committed by fit2-zhao
parent e30207a72f
commit 240cdbddf4
4 changed files with 94 additions and 36 deletions

View File

@ -8,6 +8,7 @@ import lombok.Setter;
@Setter
public class RunRequest {
private String testId;
private String poolId;
// api / case 或有这个属性值
private String reportId;
private String url;

View File

@ -7,13 +7,20 @@ import io.metersphere.api.dto.scenario.request.BodyFile;
import io.metersphere.api.service.ApiScenarioReportService;
import io.metersphere.base.domain.JarConfig;
import io.metersphere.base.domain.TestResource;
import io.metersphere.base.domain.TestResourcePool;
import io.metersphere.base.mapper.TestResourcePoolMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ResourcePoolTypeEnum;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.*;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.CompressUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.config.JmeterProperties;
import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.dto.NodeDTO;
import io.metersphere.i18n.Translator;
import io.metersphere.performance.engine.Engine;
import io.metersphere.performance.engine.EngineFactory;
import io.metersphere.service.JarConfigService;
import io.metersphere.service.SystemParameterService;
import org.apache.commons.collections.CollectionUtils;
@ -54,6 +61,8 @@ public class JMeterService {
ResourcePoolCalculation resourcePoolCalculation;
@Resource
private RestTemplate restTemplate;
@Resource
private TestResourcePoolMapper testResourcePoolMapper;
@PostConstruct
public void init() {
@ -311,42 +320,48 @@ public class JMeterService {
public void runTest(String testId, String reportId, String runMode, String testPlanScenarioId, RunModeConfig config) {
// 获取可以执行的资源池
String resourcePoolId = config.getResourcePoolId();
TestResource testResource = resourcePoolCalculation.getPool(resourcePoolId);
String configuration = testResource.getConfiguration();
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
String nodeIp = node.getIp();
Integer port = node.getPort();
BaseSystemConfigDTO baseInfo = CommonBeanFactory.getBean(SystemParameterService.class).getBaseInfo();
// 占位符
String metersphereUrl = "http://localhost:8081";
if (baseInfo != null) {
metersphereUrl = baseInfo.getUrl();
RunRequest runRequest = new RunRequest();
runRequest.setTestId(testId);
if (ApiRunMode.API_PLAN.name().equals(runMode)) {
runRequest.setReportId(reportId);
}
try {
RunRequest runRequest = new RunRequest();
runRequest.setTestId(testId);
if (ApiRunMode.API_PLAN.name().equals(runMode)) {
runRequest.setReportId(reportId);
runRequest.setPoolId(resourcePoolId);
// 占位符
String platformUrl = "http://localhost:8081";
if (baseInfo != null) {
platformUrl = baseInfo.getUrl();
}
platformUrl += "/api/jmeter/download?testId=" + testId + "&reportId=" + reportId + "&testPlanScenarioId" + "&runMode=" + runMode;
if (StringUtils.isNotEmpty(testPlanScenarioId)) {
platformUrl += "=" + testPlanScenarioId;
}
runRequest.setUrl(platformUrl);
runRequest.setRunMode(runMode);
// 如果是K8S调用
TestResourcePool pool = testResourcePoolMapper.selectByPrimaryKey(resourcePoolId);
if (pool != null && pool.getApi() && pool.getType().equals(ResourcePoolTypeEnum.K8S.name())) {
final Engine engine = EngineFactory.createApiEngine(runRequest);
engine.start();
} else {
TestResource testResource = resourcePoolCalculation.getPool(resourcePoolId);
String configuration = testResource.getConfiguration();
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
String nodeIp = node.getIp();
Integer port = node.getPort();
try {
String uri = String.format(BASE_URL + "/jmeter/api/start", nodeIp, port);
ResponseEntity<String> result = restTemplate.postForEntity(uri, runRequest, String.class);
if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) {
// 清理零时报告
ApiScenarioReportService apiScenarioReportService = CommonBeanFactory.getBean(ApiScenarioReportService.class);
apiScenarioReportService.delete(reportId);
MSException.throwException("执行失败:" + result);
}
} catch (Exception e) {
e.printStackTrace();
MSException.throwException(e.getMessage());
}
metersphereUrl += "/api/jmeter/download?testId=" + testId + "&reportId=" + reportId + "&testPlanScenarioId" + "&runMode=" + runMode;
if (StringUtils.isNotEmpty(testPlanScenarioId)) {
metersphereUrl += "=" + testPlanScenarioId;
}
runRequest.setUrl(metersphereUrl);
runRequest.setRunMode(runMode);
String uri = String.format(BASE_URL + "/jmeter/api/start", nodeIp, port);
ResponseEntity<String> result = restTemplate.postForEntity(uri, runRequest, String.class);
if (result == null || !StringUtils.equals("SUCCESS", result.getBody())) {
// 清理零时报告
ApiScenarioReportService apiScenarioReportService = CommonBeanFactory.getBean(ApiScenarioReportService.class);
apiScenarioReportService.delete(reportId);
MSException.throwException("执行失败:" + result);
}
} catch (Exception e) {
e.printStackTrace();
MSException.throwException(e.getMessage());
}
}
}

View File

@ -3,6 +3,7 @@ package io.metersphere.performance.engine;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.RunRequest;
import io.metersphere.base.domain.LoadTestWithBLOBs;
import io.metersphere.base.domain.TestResource;
import io.metersphere.base.domain.TestResourcePool;
@ -32,7 +33,6 @@ public abstract class AbstractEngine implements Engine {
protected PerformanceTestService performanceTestService;
protected Integer threadNum;
protected List<TestResource> resourceList;
private final TestResourcePoolService testResourcePoolService;
private final TestResourceService testResourceService;
@ -45,7 +45,39 @@ public abstract class AbstractEngine implements Engine {
this.startTime = System.currentTimeMillis();
this.reportId = UUID.randomUUID().toString();
}
protected void initApiConfig(RunRequest runRequest) {
String resourcePoolId = runRequest.getPoolId();
TestResourcePool resourcePool = testResourcePoolService.getResourcePool(resourcePoolId);
if (resourcePool == null || StringUtils.equals(resourcePool.getStatus(), ResourceStatusEnum.DELETE.name())) {
MSException.throwException("Resource Pool is empty");
}
if (!ResourcePoolTypeEnum.K8S.name().equals(resourcePool.getType())
&& !ResourcePoolTypeEnum.NODE.name().equals(resourcePool.getType())) {
MSException.throwException("Invalid Resource Pool type.");
}
if (!StringUtils.equals(resourcePool.getStatus(), ResourceStatusEnum.VALID.name())) {
MSException.throwException("Resource Pool Status is not VALID");
}
// image
String image = resourcePool.getImage();
if (StringUtils.isNotEmpty(image)) {
JMETER_IMAGE = image;
}
// heap
String heap = resourcePool.getHeap();
if (StringUtils.isNotEmpty(heap)) {
HEAP = heap;
}
// gc_algo
String gcAlgo = resourcePool.getGcAlgo();
if (StringUtils.isNotEmpty(gcAlgo)) {
GC_ALGO = gcAlgo;
}
this.resourceList = testResourceService.getResourcesByPoolId(resourcePool.getId());
if (CollectionUtils.isEmpty(this.resourceList)) {
MSException.throwException("Test Resource is empty");
}
}
protected void init(LoadTestWithBLOBs loadTest) {
if (loadTest == null) {
MSException.throwException("LoadTest is null.");

View File

@ -3,6 +3,7 @@ package io.metersphere.performance.engine;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.Application;
import io.metersphere.api.dto.RunRequest;
import io.metersphere.base.domain.FileContent;
import io.metersphere.base.domain.FileMetadata;
import io.metersphere.base.domain.LoadTestWithBLOBs;
@ -88,6 +89,15 @@ public class EngineFactory {
return null;
}
public static Engine createApiEngine(RunRequest runRequest) {
try {
return (Engine) ConstructorUtils.invokeConstructor(kubernetesTestEngineClass, runRequest);
} catch (Exception e) {
LogUtil.error(e);
return null;
}
}
public static EngineContext createContext(LoadTestWithBLOBs loadTest, double[] ratios, String reportId, int resourceIndex) {
final List<FileMetadata> fileMetadataList = performanceTestService.getFileMetadataByTestId(loadTest.getId());
if (org.springframework.util.CollectionUtils.isEmpty(fileMetadataList)) {