refactor(项目管理): 优化项目显示或执行资源池逻辑

This commit is contained in:
wxg0103 2024-02-23 11:41:38 +08:00 committed by 刘瑞斌
parent f66e917faf
commit 8bba1cdc64
10 changed files with 162 additions and 18 deletions

View File

@ -268,6 +268,8 @@ INSERT into system_parameter values('base.prometheus.host', 'http://prometheus:9
INSERT INTO test_resource_pool (id, name, type, description, enable, create_time, update_time, create_user, api_test, load_test, ui_test, all_org, deleted) VALUES (uuid_short(), '默认资源池', 'Node', '系统初始化资源池', true, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', true, true, true, true, false);
INSERT INTO test_resource_pool_blob (id, configuration) VALUES ((select id from test_resource_pool where name = '默认资源池'), 0x504B0304140008080800FD967E57000000000000000000000000030000007A6970ED58518F9B3810FE2B08F5313459A93ADDF1C6266E966D422260AB3B351572C049DC808D8CD96B14E5BF770C9B2C21987DE8D3E9962798F9FCF99B61EC311CCD94E32424857433BC25A66D9A838BE981E0BCB6309E9062460B69DADF8E265556898BBD254AC6880040CE05F8CC3F47A3113C659C51C90518FEBAAB0C316771290461D22BB3358CB0C17EFA3EA8A85899A60353F23D61E707863352E4382667C32D416DCF7912EE04C14971B6FCE0EB09D950104039F09938A75F8928E0C136D658C6BBE1F3DD8AED294B6CE391AF572C23122758627BC50C23C56B9216D5AD6148C8814501F7E118A2208CDCC949399438657B5CDC479E3347602C72125783722C709A929416996DDC298B24599E62495E38AF6653D7D58C3DB31AC6651275E14D15E3A1311072E130499D5B0FF804D910C85F32290565DB20DE91A44CE1CEDD327E31A39F242E55DEAEC61A865571BFF08644642DFF258E80A4248637DFE187D055F6D14F9052A8D7517482D4647B72B0CF69E8C61806CF89C06A26C3653ACC334E4BA29BA69EAA9DE3E62579CE53BE3D7C5172F625541D23A0EA23E5C31D2FA42A83F6A07F09DDEE24BCF9D1E8EC82CA9598C22A690AB1C09C65186AB09DE862D7B65871DB32846567A9FC7CBC4613F67CC357176B103A7E1885EE1CB5155739B28D95F9E1F80A3AADCC6E9EA9EF784F33C777C37F7A881A282DD3E31C85C88F7CB45CF86110858BA53BD650C24AEB009FBA792B64B07C403E8A9EFC9996B285D3B0F928583CF9630405A2656A60342CF7CEF80BF226D1CC0D42E421BF27756DA8367FF78B451884BEB38C02E47F8550B4FA6E90BA589DD05DF448ABFC5A3DF5BB893EBB9EA34B7A45D28069B95E96A436A2EE257B19FDE0236712794FF31E1DAF20AD8A07E42CB51294535B335588BD15F382E8670085B337966C0BD9F376CE35EA4DD0DFBD844DA0966FB698BEB1642F084D8CD371E4CCA6BA7A833DA4F65F8DA6EA88D2D80FDCB93345B788259C03963CA5316CDBEEC6E372091D074E0E4D602DE207746322AEFA249C63DA1DC37ADDC397E0B68D3FE094336A2BCF05973CE62914E0F8AA6E9E795A6664CE4BD6C19C29F312CB9D6D0CD58EDE66AD7556BD70435352F48DAFA3B1A06575B380A34DF29B7D684B98EAC2C4124425EEBD1DDDF0BEB7A3B6BEF776D4A1E3BD1DE908FF4FEDA8DE45FF1BBD03629058C873601E797E6DA4B5EAEBEF1DF80A96870985EFB5E3E936F22E916F8D694832076642F2941F3CF09C7F0494742A6862DAE64ECADC1E0E0BF83665B4CCAC5DB9B63FC105A3B65424E39B5F0B9F0626175B57FD53F8F6FDF40B504B0708DDC8DEC7B603000023110000504B01021400140008080800FD967E57DDC8DEC7B6030000231100000300000000000000000000000000000000007A6970504B0506000000000100010031000000E70300000000);
-- 初始化默认项目与默认资源池的关系
INSERT INTO project_test_resource_pool (project_id, test_resource_pool_id) VALUES ('100001100001', (SELECT id FROM test_resource_pool WHERE name = '默认资源池'));
-- 初始化组织功能用例字段
INSERT INTO custom_field(id, name, scene, `type`, remark, internal, scope_type, create_time, update_time, create_user, scope_id) VALUES(UUID_SHORT(), 'functional_priority', 'FUNCTIONAL', 'SELECT', '', 1, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001');
INSERT INTO custom_field_option (field_id,value,`text`,internal) VALUES ((select id from custom_field where name = 'functional_priority'), 'P0', 'P0', 1);

View File

@ -34,6 +34,7 @@ public class ProjectApplicationType {
LOAD_TEST_SHARE_REPORT,
LOAD_TEST_SCRIPT_REVIEWER_ENABLE,
LOAD_TEST_SCRIPT_REVIEWER_ID,
LOAD_TEST_RESOURCE_POOL_ID
}
@ -62,7 +63,7 @@ public class ProjectApplicationType {
CASE_ENABLE,
}
public enum PLATFORM_DEMAND_CONFIG{
public enum PLATFORM_DEMAND_CONFIG {
DEMAND_PLATFORM_CONFIG
}
@ -71,7 +72,7 @@ public class ProjectApplicationType {
BUG_SYNC
}
public enum PLATFORM_BUG_CONFIG{
public enum PLATFORM_BUG_CONFIG {
BUG_PLATFORM_CONFIG
}

View File

@ -37,6 +37,7 @@ import io.metersphere.system.utils.TaskRunnerClient;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.util.JMeterUtils;
import org.springframework.context.i18n.LocaleContextHolder;
@ -396,7 +397,12 @@ public class ApiExecuteService {
ProjectApplication resourcePoolConfig = projectApplicationService.getByType(projectId, ProjectApplicationType.API.API_RESOURCE_POOL_ID.name());
// 没有配置接口默认资源池
if (resourcePoolConfig == null || StringUtils.isBlank(resourcePoolConfig.getTypeValue())) {
throw new MSException(ApiResultCode.EXECUTE_RESOURCE_POOL_NOT_CONFIG);
Map<String, Object> configMap = new HashMap<>();
projectApplicationService.putResourcePool(projectId, configMap, "apiTest");
if (MapUtils.isEmpty(configMap)) {
throw new MSException(ApiResultCode.EXECUTE_RESOURCE_POOL_NOT_CONFIG);
}
return (String) configMap.get(ProjectApplicationType.API.API_RESOURCE_POOL_ID.name());
}
return StringUtils.isBlank(resourcePoolConfig.getTypeValue()) ? null : resourcePoolConfig.getTypeValue();
}

View File

@ -24,11 +24,14 @@ import io.metersphere.api.parser.ImportParserFactory;
import io.metersphere.api.parser.TestElementParserFactory;
import io.metersphere.api.service.ApiCommonService;
import io.metersphere.api.service.ApiFileResourceService;
import io.metersphere.api.service.BaseFileManagementTestService;
import io.metersphere.api.service.BaseResourcePoolTestService;
import io.metersphere.api.utils.ApiDataUtils;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.domain.ProjectTestResourcePool;
import io.metersphere.project.domain.ProjectTestResourcePoolExample;
import io.metersphere.project.dto.filemanagement.FileInfo;
import io.metersphere.api.service.BaseFileManagementTestService;
import io.metersphere.project.mapper.ProjectTestResourcePoolMapper;
import io.metersphere.project.service.FileAssociationService;
import io.metersphere.sdk.constants.DefaultRepositoryDir;
import io.metersphere.sdk.constants.PermissionConstants;
@ -40,7 +43,9 @@ import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.TestResourcePool;
import io.metersphere.system.domain.TestResourcePoolExample;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.mapper.TestResourcePoolMapper;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
@ -84,6 +89,10 @@ public class ApiDebugControllerTests extends BaseTest {
private BaseFileManagementTestService baseFileManagementTestService;
@Resource
private ApiCommonService apiCommonService;
@Resource
private ProjectTestResourcePoolMapper projectTestResourcePoolMapper;
@Resource
private TestResourcePoolMapper testResourcePoolMapper;
private static ApiDebug addApiDebug;
private static ApiDebug anotherAddApiDebug;
private static String fileMetadataId;
@ -403,6 +412,9 @@ public class ApiDebugControllerTests extends BaseTest {
request.setReportId(IDGenerator.nextStr());
request.setProjectId(DEFAULT_PROJECT_ID);
ProjectTestResourcePoolExample projectTestResourcePoolExample = new ProjectTestResourcePoolExample();
projectTestResourcePoolExample.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID);
projectTestResourcePoolMapper.deleteByExample(projectTestResourcePoolExample);
// @校验组织没有资源池权限异常
assertErrorCode(this.requestPost(DEBUG, request), ApiResultCode.EXECUTE_RESOURCE_POOL_NOT_CONFIG);
TestResourcePool resourcePool = baseResourcePoolTestService.insertResourcePool();
@ -410,6 +422,17 @@ public class ApiDebugControllerTests extends BaseTest {
// @校验项目没有资源池权限异常
assertErrorCode(this.requestPost(DEBUG, request), ApiResultCode.EXECUTE_RESOURCE_POOL_NOT_CONFIG);
TestResourcePoolExample example = new TestResourcePoolExample();
example.createCriteria().andNameEqualTo("默认资源池");
List<TestResourcePool> testResourcePools = testResourcePoolMapper.selectByExample(example);
Assertions.assertFalse(testResourcePools.isEmpty());
ProjectTestResourcePool projectTestResourcePool = new ProjectTestResourcePool();
projectTestResourcePool.setProjectId(DEFAULT_PROJECT_ID);
projectTestResourcePool.setTestResourcePoolId(testResourcePools.get(0).getId());
projectTestResourcePoolMapper.insert(projectTestResourcePool);
this.requestPost(DEBUG, request);
projectTestResourcePoolMapper.deleteByExample(projectTestResourcePoolExample);
baseResourcePoolTestService.insertResourcePoolProject(resourcePool);
baseResourcePoolTestService.insertProjectApplication(resourcePool);
// @校验资源池调用失败
@ -492,6 +515,7 @@ public class ApiDebugControllerTests extends BaseTest {
/**
* 测试关联的文件更新
*
* @throws Exception
*/
public void testHandleFileAssociationUpgrade() throws Exception {

View File

@ -80,7 +80,7 @@ public class ProjectApplicationController {
@Operation(summary = "UI测试-获取配置")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_UI_READ)
public Map<String, Object> getUI(@Validated @RequestBody ProjectApplicationRequest request) {
List<String> types = Arrays.asList(ProjectApplicationType.UI.values()).stream().map(ProjectApplicationType.UI::name).collect(Collectors.toList());
List<String> types = Arrays.stream(ProjectApplicationType.UI.values()).map(ProjectApplicationType.UI::name).collect(Collectors.toList());
return projectApplicationService.get(request, types);
}
@ -108,7 +108,7 @@ public class ProjectApplicationController {
@Operation(summary = "性能测试-获取配置")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_PERFORMANCE_TEST_READ)
public Map<String, Object> getPerformanceTest(@Validated @RequestBody ProjectApplicationRequest request) {
List<String> types = Arrays.asList(ProjectApplicationType.LOAD_TEST.values()).stream().map(ProjectApplicationType.LOAD_TEST::name).collect(Collectors.toList());
List<String> types = Arrays.stream(ProjectApplicationType.LOAD_TEST.values()).map(ProjectApplicationType.LOAD_TEST::name).collect(Collectors.toList());
return projectApplicationService.get(request, types);
}
@ -136,7 +136,7 @@ public class ProjectApplicationController {
@Operation(summary = "接口测试-获取配置")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_API_READ)
public Map<String, Object> getApi(@Validated @RequestBody ProjectApplicationRequest request) {
List<String> types = Arrays.asList(ProjectApplicationType.API.values()).stream().map(ProjectApplicationType.API::name).collect(Collectors.toList());
List<String> types = Arrays.stream(ProjectApplicationType.API.values()).map(ProjectApplicationType.API::name).collect(Collectors.toList());
Map<String, Object> configMap = projectApplicationService.get(request, types);
int errorNum = projectApplicationService.getFakeErrorList(request.getProjectId());
configMap.put("FAKE_ERROR_NUM", errorNum);

View File

@ -1,6 +1,7 @@
package io.metersphere.project.mapper;
import io.metersphere.project.domain.Project;
import io.metersphere.project.domain.ProjectTestResourcePool;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -17,4 +18,9 @@ public interface ExtProjectMapper {
List<Project> getProjectByOrgId(@Param("userId") String userId, @Param("organizationId") String organizationId);
int resourcePoolIsExist(@Param("poolId") String poolId, @Param("projectId") String projectId, @Param("type") String type);
int resourcePoolIsExistByOrg(@Param("poolId") String string, @Param("projectId") String projectId, @Param("type") String type);
List<ProjectTestResourcePool> getResourcePool(@Param("projectId") String projectId, @Param("type") String type);
}

View File

@ -52,4 +52,26 @@
order by create_time desc
limit 100
</select>
<select id="resourcePoolIsExist" resultType="int">
select count(t.id) from test_resource_pool t left join project_test_resource_pool p on
t.id = p.test_resource_pool_id
where p.project_id = #{projectId} and t.id = #{poolId}
and t.${type} = 1 and t.enable = 1 and t.deleted = 0
</select>
<select id="resourcePoolIsExistByOrg" resultType="java.lang.Integer">
select count(t.id) from test_resource_pool_organization o
left join test_resource_pool t on t.id = o.test_resource_pool_id
left join project_test_resource_pool p on t.id = p.test_resource_pool_id
where p.project_id = #{projectId} and t.id = #{poolId}
and t.${type} = 1 and t.enable = 1 and t.deleted = 0
</select>
<select id="getResourcePool" resultType="io.metersphere.project.domain.ProjectTestResourcePool">
select p.*
from project_test_resource_pool p left join test_resource_pool t on
t.id = p.test_resource_pool_id
where p.project_id = #{projectId}
and t.enable = 1
and t.deleted = 0
and t.${type} = 1
</select>
</mapper>

View File

@ -3,11 +3,7 @@ package io.metersphere.project.service;
import io.metersphere.plugin.platform.spi.AbstractPlatformPlugin;
import io.metersphere.plugin.platform.spi.Platform;
import io.metersphere.plugin.sdk.spi.MsPlugin;
import io.metersphere.project.domain.FakeError;
import io.metersphere.project.domain.FakeErrorExample;
import io.metersphere.project.domain.Project;
import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.domain.ProjectApplicationExample;
import io.metersphere.project.domain.*;
import io.metersphere.project.dto.ModuleDTO;
import io.metersphere.project.mapper.*;
import io.metersphere.project.request.ProjectApplicationRequest;
@ -22,13 +18,14 @@ import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.Plugin;
import io.metersphere.system.domain.ServiceIntegration;
import io.metersphere.system.domain.TestResourcePoolExample;
import io.metersphere.system.domain.User;
import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
import io.metersphere.system.mapper.PluginMapper;
import io.metersphere.system.mapper.ServiceIntegrationMapper;
import io.metersphere.system.mapper.TestResourcePoolMapper;
import io.metersphere.system.service.BaseBugScheduleService;
import io.metersphere.system.service.PlatformPluginService;
import io.metersphere.system.service.PluginLoadService;
@ -56,7 +53,7 @@ public class ProjectApplicationService {
private ExtProjectUserRoleMapper extProjectUserRoleMapper;
@Resource
private ServiceIntegrationMapper serviceIntegrationMapper;
private ProjectTestResourcePoolMapper projectTestResourcePoolMapper;
@Resource
private PluginMapper pluginMapper;
@ -77,6 +74,8 @@ public class ProjectApplicationService {
private ServiceIntegrationService serviceIntegrationService;
@Resource
private ProjectMapper projectMapper;
@Resource
private TestResourcePoolMapper testResourcePoolMapper;
/**
* 更新配置信息
@ -126,11 +125,63 @@ public class ProjectApplicationService {
List<ProjectApplication> applicationList = projectApplicationMapper.selectByExample(projectApplicationExample);
if (CollectionUtils.isNotEmpty(applicationList)) {
configMap = applicationList.stream().collect(Collectors.toMap(ProjectApplication::getType, ProjectApplication::getTypeValue));
putResourcePool(request.getProjectId(), configMap, request.getType());
return configMap;
}
putResourcePool(request.getProjectId(), configMap, request.getType());
return configMap;
}
public void putResourcePool(String projectId, Map<String, Object> configMap, String type) {
//如果存在 需要判断 如果不存在 需要判断资源池在不在 是否还在关系表中 如果不存在 需要删除 并重新处理数据
String poolType = null;
String moduleType = null;
if (StringUtils.isBlank(type)) {
return;
}
switch (type) {
case "apiTest" -> {
poolType = ProjectApplicationType.API.API_RESOURCE_POOL_ID.name();
moduleType = "api_test";
}
case "uiTest" -> {
poolType = ProjectApplicationType.UI.UI_RESOURCE_POOL_ID.name();
moduleType = "ui_test";
}
case "loadTest" -> {
poolType = ProjectApplicationType.LOAD_TEST.LOAD_TEST_RESOURCE_POOL_ID.name();
moduleType = "load_test";
}
default -> {
}
}
if (StringUtils.isNotBlank(poolType) && StringUtils.isNotBlank(moduleType)) {
if (configMap.containsKey(poolType)) {
//如果是适用于所有的组织
int count = 0;
TestResourcePoolExample example = new TestResourcePoolExample();
example.createCriteria().andIdEqualTo(configMap.get(poolType).toString()).andAllOrgEqualTo(true);
if (testResourcePoolMapper.countByExample(example) > 0) {
count = extProjectMapper.resourcePoolIsExist(configMap.get(poolType).toString(), projectId, moduleType);
} else {
//指定组织 则需要关联组织-资源池的关系表 看看是否再全部存在
count = extProjectMapper.resourcePoolIsExistByOrg(configMap.get(poolType).toString(), projectId, moduleType);
}
if (count == 0) {
configMap.remove(poolType);
}
}
if (!configMap.containsKey(poolType)) {
List<ProjectTestResourcePool> projectTestResourcePools = extProjectMapper.getResourcePool(projectId, moduleType);
if (CollectionUtils.isNotEmpty(projectTestResourcePools)) {
projectTestResourcePools.sort(Comparator.comparing(ProjectTestResourcePool::getTestResourcePoolId));
configMap.put(poolType, projectTestResourcePools.getFirst().getTestResourcePoolId());
}
}
}
}
/**
* 获取 项目成员脚本审核人

View File

@ -5,6 +5,7 @@ import io.metersphere.project.controller.param.ProjectApplicationRequestDefiniti
import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.domain.ProjectApplicationExample;
import io.metersphere.project.mapper.ProjectApplicationMapper;
import io.metersphere.project.mapper.ProjectTestResourcePoolMapper;
import io.metersphere.project.request.ProjectApplicationRequest;
import io.metersphere.project.service.ProjectApplicationService;
import io.metersphere.sdk.constants.ProjectApplicationType;
@ -13,11 +14,11 @@ import io.metersphere.sdk.util.Translator;
import io.metersphere.system.base.BasePluginTestService;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.Plugin;
import io.metersphere.system.domain.ServiceIntegration;
import io.metersphere.system.domain.ServiceIntegrationExample;
import io.metersphere.system.domain.*;
import io.metersphere.system.dto.request.ServiceIntegrationUpdateRequest;
import io.metersphere.system.mapper.ServiceIntegrationMapper;
import io.metersphere.system.mapper.TestResourcePoolMapper;
import io.metersphere.system.mapper.TestResourcePoolOrganizationMapper;
import jakarta.annotation.Resource;
import lombok.Getter;
import lombok.Setter;
@ -33,6 +34,7 @@ import org.springframework.test.web.servlet.MvcResult;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND;
@ -54,6 +56,12 @@ public class ProjectApplicationControllerTests extends BaseTest {
private ProjectApplicationService projectApplicationService;
@Resource
private ProjectApplicationMapper projectApplicationMapper;
@Resource
private TestResourcePoolMapper testResourcePoolMapper;
@Resource
private ProjectTestResourcePoolMapper projectTestResourcePoolMapper;
@Resource
private TestResourcePoolOrganizationMapper testResourcePoolOrganizationMapper;
public static final String PROJECT_ID = "project_application_test_id";
public static final String TIME_TYPE_VALUE = "3M";
@ -772,4 +780,28 @@ public class ProjectApplicationControllerTests extends BaseTest {
Assertions.assertTrue(projectApplicationService.isPlatformSyncMethodByIncrement("default-project-for-application"));
Assertions.assertFalse(projectApplicationService.isPlatformSyncMethodByIncrement("default-project-for-application-not-exist"));
}
@Test
@Order(100)
public void testResourcePool() {
// 校验资源池 默认资源池
String projectId = DEFAULT_PROJECT_ID;
Map<String, Object> configMap = new HashMap<>();
projectApplicationService.putResourcePool(projectId, configMap, "apiTest");
projectApplicationService.putResourcePool(projectId, configMap, "uiTest");
projectApplicationService.putResourcePool(projectId, configMap, "loadTest");
//项目与资源池有关系
TestResourcePoolExample example = new TestResourcePoolExample();
example.createCriteria().andNameEqualTo("默认资源池");
List<TestResourcePool> testResourcePools = testResourcePoolMapper.selectByExample(example);
Assertions.assertFalse(testResourcePools.isEmpty());
configMap.put(ProjectApplicationType.API.API_RESOURCE_POOL_ID.name(), testResourcePools.getFirst().getId());
projectApplicationService.putResourcePool(projectId, configMap, "apiTest");
TestResourcePool testResourcePool = testResourcePoolMapper.selectByPrimaryKey(testResourcePools.getFirst().getId());
testResourcePool.setAllOrg(false);
testResourcePoolMapper.updateByPrimaryKeySelective(testResourcePool);
projectApplicationService.putResourcePool(projectId, configMap, "apiTest");
}
}

View File

@ -19,7 +19,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import java.util.Map;
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@AutoConfigureMockMvc
public class ProjectVersionResourceTests extends BaseTest {