feat(接口测试): 支持服务端调试更新环境变量

This commit is contained in:
fit2-zhao 2024-03-26 14:45:44 +08:00 committed by Craftsman
parent 74fb26bd1d
commit 7ae3ea52fb
2 changed files with 169 additions and 0 deletions

View File

@ -1,7 +1,9 @@
package io.metersphere.api.listener;
import io.metersphere.api.service.ApiEnvironmentService;
import io.metersphere.sdk.constants.KafkaTopicConstants;
import io.metersphere.sdk.dto.SocketMsgDTO;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.WebSocketUtils;
@ -10,6 +12,8 @@ import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 后端调试消息监听器
*/
@ -17,13 +21,25 @@ import org.springframework.stereotype.Component;
public class DebugListener {
public static final String DEBUG_CONSUME_ID = "MS-API-DEBUG-CONSUME";
private ApiEnvironmentService apiEnvironmentService;
;
@KafkaListener(id = DEBUG_CONSUME_ID, topics = KafkaTopicConstants.API_REPORT_DEBUG_TOPIC, groupId = DEBUG_CONSUME_ID + "_" + "${random.uuid}")
public void debugConsume(ConsumerRecord<?, String> record) {
try {
if (apiEnvironmentService == null) {
apiEnvironmentService = CommonBeanFactory.getBean(ApiEnvironmentService.class);
}
LogUtils.info("接收到执行结果:{}", record.key());
if (ObjectUtils.isNotEmpty(record.value()) && WebSocketUtils.has(record.key().toString())) {
SocketMsgDTO dto = JSON.parseObject(record.value(), SocketMsgDTO.class);
// 处理环境变量
if (dto.getTaskResult() instanceof List environmentVariables) {
LogUtils.info("{} 处理环境变量", record.key());
apiEnvironmentService.parseEnvironment(environmentVariables);
}
LogUtils.info("{} 推送执行结果类型【 {} 】", record.key(), dto.getMsgType());
WebSocketUtils.sendMessageSingle(dto);
}

View File

@ -0,0 +1,153 @@
package io.metersphere.api.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.metersphere.sdk.domain.EnvironmentBlob;
import io.metersphere.sdk.mapper.EnvironmentBlobMapper;
import io.metersphere.sdk.util.LogUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class ApiEnvironmentService {
private static final String COMMON_CONFIG = "config";
private static final String VARIABLES = "commonVariables";
private static final String VALUE = "value";
private static final String ENABLE = "enable";
private static final String NAME = "key";
private static final String ENV_STR = "MS.ENV.";
@Resource
private EnvironmentBlobMapper environmentBlobMapper;
private final ObjectMapper objectMapper = new ObjectMapper();
public void parseEnvironment(List<String> environmentVariables) {
try {
environmentVariables.forEach(this::parseEvn);
} catch (Exception e) {
LogUtils.error(e);
}
}
private void parseEvn(String envStr) {
String[] envStringArr = envStr.split(StringUtils.LF);
Map<String, Map<String, String>> envVarsMap = new HashMap<>();
for (String env : envStringArr) {
if (StringUtils.contains(env, "=")) {
String[] envItem = env.split("=");
if (envItem.length == 0) {
continue;
}
String jmeterVarKey = envItem[0];
if (checkValidity(jmeterVarKey)) {
String[] envAndKeyArr = jmeterVarKey.substring(ENV_STR.length()).split("\\.");
if (envAndKeyArr.length == 0) {
continue;
}
String envId = envAndKeyArr[0];
String key = StringUtils.join(ArrayUtils.remove(envAndKeyArr, 0), ".");
String value = StringUtils.substring(env, jmeterVarKey.length() + 1);
if (StringUtils.isNoneEmpty(envId, key)) {
envVarsMap.computeIfAbsent(envId, k -> new HashMap<>()).put(key, value);
}
}
}
}
if (!envVarsMap.isEmpty()) {
envVarsMap.forEach(this::addParam);
}
}
private boolean checkValidity(String str) {
return str != null && str.startsWith(ApiEnvironmentService.ENV_STR);
}
private void addParam(String environmentId, Map<String, String> varMap) {
if (varMap.isEmpty()) {
return;
}
EnvironmentBlob environment = environmentBlobMapper.selectByPrimaryKey(environmentId);
if (environment == null) {
return;
}
try {
JsonNode configObj = objectMapper.readTree(new String(environment.getConfig(), StandardCharsets.UTF_8));
if (configObj.isMissingNode() || !configObj.has(VARIABLES)) {
ObjectNode newCommonConfig = objectMapper.createObjectNode();
List<JsonNode> variables = createArray(varMap);
newCommonConfig.putArray(VARIABLES).addAll(variables);
((ObjectNode) configObj).set(COMMON_CONFIG, newCommonConfig);
return;
}
JsonNode variables = configObj.path(VARIABLES);
if (variables.isMissingNode()) {
return;
}
boolean envNeedUpdate = false;
for (Map.Entry<String, String> entry : varMap.entrySet()) {
boolean contains = false;
Iterator<JsonNode> elements = variables.elements();
int length = 0;
while (elements.hasNext()) {
length++;
JsonNode jsonObj = elements.next();
if (jsonObj.has(NAME) && jsonObj.has(VALUE)
&& jsonObj.get(NAME).asText().equals(entry.getKey())) {
if (jsonObj.get(VALUE).asText().equals(entry.getValue())) {
break;
}
((ObjectNode) jsonObj).put(VALUE, entry.getValue());
envNeedUpdate = true;
break;
} else {
contains = true;
envNeedUpdate = true;
}
}
if (contains) {
ObjectNode itemObj = objectMapper.createObjectNode();
itemObj.put(NAME, entry.getKey());
itemObj.put(VALUE, entry.getValue());
itemObj.put(ENABLE, true);
((ArrayNode) variables).set(length - 1, itemObj);
((ObjectNode) configObj).set(VARIABLES, variables);
}
}
if (envNeedUpdate) {
environment.setConfig(objectMapper.writeValueAsBytes(configObj));
environmentBlobMapper.updateByPrimaryKeyWithBLOBs(environment);
}
} catch (JsonProcessingException ex) {
LogUtils.error("Setting environment variables exception", ex);
}
}
private List<JsonNode> createArray(Map<String, String> varMap) {
return varMap.entrySet().stream()
.map(entry -> objectMapper.createObjectNode()
.put(NAME, entry.getKey())
.put(VALUE, entry.getValue())
.put(ENABLE, true))
.collect(Collectors.toList());
}
}