* 新增根据配置信息检索内容的功能 * use offer replace add * use offer replace add * use offer replace add * update exception type and limit some config as configurable * update * update params * update params * update params
This commit is contained in:
parent
67d5acc892
commit
a6332b250d
@ -290,4 +290,8 @@ public class Constants {
|
||||
public static final int LIMIT_ERROR_CODE = 429;
|
||||
|
||||
public static final String NACOS_PLUGIN_DATASOURCE_LOG = "nacos.plugin.datasource.log.enabled";
|
||||
|
||||
public static final String CONFIG_SEARCH_BLUR = "blur";
|
||||
|
||||
public static final String CONFIG_SEARCH_ACCURATE = "accurate";
|
||||
}
|
||||
|
@ -68,4 +68,10 @@ public class PropertiesConstant {
|
||||
|
||||
public static final String EMBEDDED_STORAGE = "embeddedStorage";
|
||||
|
||||
public static final String SEARCH_MAX_CAPACITY = "nacos.config.search.max_capacity";
|
||||
|
||||
public static final String SEARCH_MAX_THREAD = "nacos.config.search.max_thread";
|
||||
|
||||
public static final String SEARCH_WAIT_TIMEOUT = "nacos.config.search.wait_timeout";
|
||||
|
||||
}
|
||||
|
@ -27,14 +27,19 @@ import com.alibaba.nacos.common.utils.Pair;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.controller.ConfigServletInner;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfo;
|
||||
import com.alibaba.nacos.config.server.model.ConfigRequestInfo;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.model.form.ConfigForm;
|
||||
import com.alibaba.nacos.config.server.service.ConfigDetailService;
|
||||
import com.alibaba.nacos.config.server.service.ConfigOperationService;
|
||||
import com.alibaba.nacos.config.server.utils.ParamUtils;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.constant.SignType;
|
||||
import com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -46,6 +51,8 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Special controller v2 for soft load client to publish data.
|
||||
@ -58,14 +65,18 @@ import java.io.IOException;
|
||||
@RestController
|
||||
@RequestMapping(Constants.CONFIG_CONTROLLER_V2_PATH)
|
||||
public class ConfigControllerV2 {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigControllerV2.class);
|
||||
|
||||
private final ConfigServletInner inner;
|
||||
|
||||
private final ConfigOperationService configOperationService;
|
||||
|
||||
public ConfigControllerV2(ConfigServletInner inner, ConfigOperationService configOperationService) {
|
||||
private final ConfigDetailService configDetailService;
|
||||
|
||||
public ConfigControllerV2(ConfigServletInner inner, ConfigOperationService configOperationService, ConfigDetailService configDetailService) {
|
||||
this.inner = inner;
|
||||
this.configOperationService = configOperationService;
|
||||
this.configDetailService = configDetailService;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -152,4 +163,36 @@ public class ConfigControllerV2 {
|
||||
String srcUser = RequestUtil.getSrcUserName(request);
|
||||
return Result.success(configOperationService.deleteConfig(dataId, group, namespaceId, tag, clientIp, srcUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* search config by config detail.
|
||||
*
|
||||
*/
|
||||
@GetMapping("/searchDetail")
|
||||
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG)
|
||||
public Page<ConfigInfo> searchConfigByDetails(@RequestParam("dataId") String dataId, @RequestParam("group") String group,
|
||||
@RequestParam(value = "appName", required = false) String appName,
|
||||
@RequestParam(value = "tenant", required = false, defaultValue = StringUtils.EMPTY) String tenant,
|
||||
@RequestParam(value = "config_tags", required = false) String configTags,
|
||||
@RequestParam(value = "config_detail") String configDetail,
|
||||
@RequestParam(value = "search", defaultValue = "blur", required = false) String search,
|
||||
@RequestParam("pageNo") int pageNo, @RequestParam("pageSize") int pageSize) throws NacosException {
|
||||
Map<String, Object> configAdvanceInfo = new HashMap<>(100);
|
||||
if (StringUtils.isNotBlank(appName)) {
|
||||
configAdvanceInfo.put("appName", appName);
|
||||
}
|
||||
if (StringUtils.isNotBlank(configTags)) {
|
||||
configAdvanceInfo.put("config_tags", configTags);
|
||||
}
|
||||
if (StringUtils.isNotBlank(configDetail)) {
|
||||
configAdvanceInfo.put("content", configDetail);
|
||||
}
|
||||
try {
|
||||
return configDetailService.findConfigInfoPage(search, pageNo, pageSize, dataId, group, tenant, configAdvanceInfo);
|
||||
} catch (Exception e) {
|
||||
String errorMsg = "serialize page error, dataId=" + dataId + ", group=" + group;
|
||||
LOGGER.error(errorMsg, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.constant.PropertiesConstant;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfo;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* config detail service.
|
||||
*
|
||||
* @author 985492783@qq.com
|
||||
* @date 2023/2/9 5:25
|
||||
*/
|
||||
@Service
|
||||
public class ConfigDetailService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigDetailService.class);
|
||||
|
||||
private final ConfigInfoPersistService configInfoPersistService;
|
||||
|
||||
private BlockingQueue<SearchEvent> eventLinkedBlockingQueue;
|
||||
|
||||
private ScheduledExecutorService clientEventExecutor;
|
||||
|
||||
/**
|
||||
* the max_capacity of eventLinkedBlockingQueue may be controlled by the properties {@link PropertiesConstant#SEARCH_MAX_CAPACITY}.
|
||||
*/
|
||||
private static int maxCapacity = 4;
|
||||
|
||||
private static final int MAX_CAPACITY = 32;
|
||||
|
||||
/**
|
||||
* the wait_timeout of search config business may be controlled by the properties {@link PropertiesConstant#SEARCH_WAIT_TIMEOUT}.
|
||||
*/
|
||||
private static long waitTimeout = 8000L;
|
||||
|
||||
/**
|
||||
* the max_thread of clientEventExecutor may be controlled by the properties {@link PropertiesConstant#SEARCH_MAX_THREAD}.
|
||||
*/
|
||||
private static int maxThread = 2;
|
||||
|
||||
private static final int MAX_THREAD = 16;
|
||||
|
||||
public ConfigDetailService(ConfigInfoPersistService configInfoPersistService) {
|
||||
this.configInfoPersistService = configInfoPersistService;
|
||||
loadSetting();
|
||||
initWorker();
|
||||
}
|
||||
|
||||
private void loadSetting() {
|
||||
setMaxCapacity(Math.min(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.SEARCH_MAX_CAPACITY,
|
||||
String.valueOf(getMaxCapacity()))), MAX_CAPACITY));
|
||||
setMaxThread(Math.min(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.SEARCH_MAX_THREAD,
|
||||
String.valueOf(getMaxThread()))), MAX_THREAD));
|
||||
setWaitTimeout(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.SEARCH_WAIT_TIMEOUT,
|
||||
String.valueOf(getWaitTimeout()))));
|
||||
}
|
||||
|
||||
/**
|
||||
* init worker thread.
|
||||
*/
|
||||
private void initWorker() {
|
||||
this.eventLinkedBlockingQueue = new LinkedBlockingQueue<>(maxCapacity);
|
||||
|
||||
clientEventExecutor = new ScheduledThreadPoolExecutor(maxThread, r -> {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("com.alibaba.nacos.config.search.worker");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
|
||||
for (int i = 0; i < maxThread; i++) {
|
||||
clientEventExecutor.submit(() -> {
|
||||
while (true) {
|
||||
try {
|
||||
SearchEvent event = eventLinkedBlockingQueue.take();
|
||||
Page<ConfigInfo> result = null;
|
||||
if (Constants.CONFIG_SEARCH_BLUR.equals(event.getType())) {
|
||||
result = configInfoPersistService.findConfigInfoLike4Page(event.pageNo, event.pageSize,
|
||||
event.dataId, event.group, event.tenant, event.configAdvanceInfo);
|
||||
} else {
|
||||
result = configInfoPersistService.findConfigInfo4Page(event.pageNo, event.pageSize,
|
||||
event.dataId, event.group, event.tenant, event.configAdvanceInfo);
|
||||
}
|
||||
synchronized (event) {
|
||||
event.setResponse(result);
|
||||
event.notifyAll();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("catch search worker error: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* block thread and use workerThread to search config.
|
||||
*/
|
||||
public Page<ConfigInfo> findConfigInfoPage(String search, int pageNo, int pageSize, String dataId, String group,
|
||||
String tenant, Map<String, Object> configAdvanceInfo) throws NacosRuntimeException {
|
||||
SearchEvent searchEvent = new SearchEvent(search, pageNo, pageSize, dataId, group, tenant,
|
||||
configAdvanceInfo);
|
||||
Page<ConfigInfo> result = null;
|
||||
try {
|
||||
synchronized (searchEvent) {
|
||||
boolean offer = eventLinkedBlockingQueue.offer(searchEvent);
|
||||
if (!offer) {
|
||||
throw new NacosRuntimeException(503, "server limit match.");
|
||||
}
|
||||
searchEvent.wait(waitTimeout);
|
||||
result = searchEvent.getResponse();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.error("get config detail timeout: {}.", e.getMessage());
|
||||
throw new NacosRuntimeException(503, "server limit match.");
|
||||
}
|
||||
if (result == null) {
|
||||
throw new NacosRuntimeException(503, "server limit match.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int getMaxCapacity() {
|
||||
return maxCapacity;
|
||||
}
|
||||
|
||||
public static void setMaxCapacity(int maxCapacity) {
|
||||
ConfigDetailService.maxCapacity = maxCapacity;
|
||||
}
|
||||
|
||||
public static long getWaitTimeout() {
|
||||
return waitTimeout;
|
||||
}
|
||||
|
||||
public static void setWaitTimeout(long waitTimeout) {
|
||||
ConfigDetailService.waitTimeout = waitTimeout;
|
||||
}
|
||||
|
||||
public static int getMaxThread() {
|
||||
return maxThread;
|
||||
}
|
||||
|
||||
public static void setMaxThread(int maxThread) {
|
||||
ConfigDetailService.maxThread = maxThread;
|
||||
}
|
||||
|
||||
public static class SearchEvent {
|
||||
private String type;
|
||||
|
||||
private int pageNo;
|
||||
|
||||
private int pageSize;
|
||||
|
||||
private String dataId;
|
||||
|
||||
private String group;
|
||||
|
||||
private String tenant;
|
||||
|
||||
private Map<String, Object> configAdvanceInfo;
|
||||
|
||||
private Page<ConfigInfo> response;
|
||||
|
||||
public SearchEvent() {
|
||||
}
|
||||
|
||||
public SearchEvent(String type, int pageNo, int pageSize, String dataId, String group, String tenant,
|
||||
Map<String, Object> configAdvanceInfo) {
|
||||
this.type = type;
|
||||
this.pageNo = pageNo;
|
||||
this.pageSize = pageSize;
|
||||
this.dataId = dataId;
|
||||
this.group = group;
|
||||
this.tenant = tenant;
|
||||
this.configAdvanceInfo = configAdvanceInfo;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getPageNo() {
|
||||
return pageNo;
|
||||
}
|
||||
|
||||
public int getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public String getDataId() {
|
||||
return dataId;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
public Map<String, Object> getConfigAdvanceInfo() {
|
||||
return configAdvanceInfo;
|
||||
}
|
||||
|
||||
public Page<ConfigInfo> getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public void setResponse(Page<ConfigInfo> response) {
|
||||
this.response = response;
|
||||
}
|
||||
}
|
||||
}
|
@ -674,6 +674,7 @@ public class EmbeddedConfigInfoPersistServiceImpl implements ConfigInfoPersistSe
|
||||
final String group, final String tenant, final Map<String, Object> configAdvanceInfo) {
|
||||
String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;
|
||||
final String appName = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("appName");
|
||||
final String content = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("content");
|
||||
final String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("config_tags");
|
||||
String sql = null;
|
||||
String sqlCount = null;
|
||||
@ -692,6 +693,10 @@ public class EmbeddedConfigInfoPersistServiceImpl implements ConfigInfoPersistSe
|
||||
paramList.add(appName);
|
||||
paramsMap.put(APP_NAME, APP_NAME);
|
||||
}
|
||||
if (!StringUtils.isBlank(content)) {
|
||||
paramList.add(content);
|
||||
paramsMap.put(CONTENT, CONTENT);
|
||||
}
|
||||
final int startRow = (pageNo - 1) * pageSize;
|
||||
if (StringUtils.isNotBlank(configTags)) {
|
||||
String[] tagArr = configTags.split(",");
|
||||
|
@ -695,6 +695,7 @@ public class ExternalConfigInfoPersistServiceImpl implements ConfigInfoPersistSe
|
||||
String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;
|
||||
PaginationHelper<ConfigInfo> helper = createPaginationHelper();
|
||||
final String appName = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("appName");
|
||||
final String content = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("content");
|
||||
final String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("config_tags");
|
||||
String sql = null;
|
||||
String sqlCount = null;
|
||||
@ -713,6 +714,10 @@ public class ExternalConfigInfoPersistServiceImpl implements ConfigInfoPersistSe
|
||||
paramList.add(appName);
|
||||
paramsMap.put(APP_NAME, APP_NAME);
|
||||
}
|
||||
if (!StringUtils.isBlank(content)) {
|
||||
paramList.add(content);
|
||||
paramsMap.put(CONTENT, CONTENT);
|
||||
}
|
||||
final int startRow = (pageNo - 1) * pageSize;
|
||||
if (StringUtils.isNotBlank(configTags)) {
|
||||
String[] tagArr = configTags.split(",");
|
||||
|
@ -18,24 +18,45 @@ package com.alibaba.nacos.config.server.controller.v2;
|
||||
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.controller.ConfigServletInner;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfo;
|
||||
import com.alibaba.nacos.config.server.model.ConfigRequestInfo;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.model.form.ConfigForm;
|
||||
import com.alibaba.nacos.config.server.service.ConfigDetailService;
|
||||
import com.alibaba.nacos.config.server.service.ConfigOperationService;
|
||||
import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
|
||||
import com.alibaba.nacos.core.auth.AuthFilter;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
@ -47,14 +68,30 @@ import static org.mockito.Mockito.when;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ConfigControllerV2Test {
|
||||
|
||||
@InjectMocks
|
||||
private AuthFilter authFilter;
|
||||
|
||||
@Mock
|
||||
private AuthConfigs authConfigs;
|
||||
|
||||
private ConfigControllerV2 configControllerV2;
|
||||
|
||||
private MockMvc mockmvc;
|
||||
|
||||
@Mock
|
||||
private ConfigServletInner inner;
|
||||
|
||||
@Mock
|
||||
private ConfigOperationService configOperationService;
|
||||
|
||||
@Mock
|
||||
private ServletContext servletContext;
|
||||
|
||||
@Mock
|
||||
private ConfigInfoPersistService configInfoPersistService;
|
||||
|
||||
private ConfigDetailService configDetailService;
|
||||
|
||||
private static final String TEST_DATA_ID = "test";
|
||||
|
||||
private static final String TEST_GROUP = "test";
|
||||
@ -69,7 +106,12 @@ public class ConfigControllerV2Test {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
configControllerV2 = new ConfigControllerV2(inner, configOperationService);
|
||||
EnvUtil.setEnvironment(new StandardEnvironment());
|
||||
when(servletContext.getContextPath()).thenReturn("/nacos");
|
||||
configDetailService = new ConfigDetailService(configInfoPersistService);
|
||||
configControllerV2 = new ConfigControllerV2(inner, configOperationService, configDetailService);
|
||||
mockmvc = MockMvcBuilders.standaloneSetup(configControllerV2).addFilter(authFilter).build();
|
||||
when(authConfigs.isAuthEnabled()).thenReturn(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -180,4 +222,89 @@ public class ConfigControllerV2Test {
|
||||
assertEquals(ErrorCode.SUCCESS.getCode(), booleanResult.getCode());
|
||||
assertEquals(true, booleanResult.getData());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigByDetail() throws Exception {
|
||||
List<ConfigInfo> configInfoList = new ArrayList<>();
|
||||
ConfigInfo configInfo = new ConfigInfo("test", "test", "test");
|
||||
configInfoList.add(configInfo);
|
||||
|
||||
Page<ConfigInfo> page = new Page<>();
|
||||
page.setTotalCount(15);
|
||||
page.setPageNumber(1);
|
||||
page.setPagesAvailable(2);
|
||||
page.setPageItems(configInfoList);
|
||||
Map<String, Object> configAdvanceInfo = new HashMap<>(8);
|
||||
configAdvanceInfo.put("content", "server.port");
|
||||
|
||||
when(configInfoPersistService.findConfigInfo4Page(1, 10, "test", "test", "", configAdvanceInfo))
|
||||
.thenReturn(page);
|
||||
|
||||
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_V2_PATH + "/searchDetail")
|
||||
.param("search", "accurate").param("dataId", "test").param("group", "test")
|
||||
.param("appName", "").param("tenant", "").param("config_tags", "")
|
||||
.param("pageNo", "1").param("pageSize", "10").param("config_detail", "server.port");
|
||||
MockHttpServletResponse response = mockmvc.perform(builder).andReturn().getResponse();
|
||||
String actualValue = response.getContentAsString();
|
||||
|
||||
JsonNode pageItemsNode = JacksonUtils.toObj(actualValue).get("pageItems");
|
||||
List resultList = JacksonUtils.toObj(pageItemsNode.toString(), List.class);
|
||||
ConfigInfo resConfigInfo = JacksonUtils.toObj(pageItemsNode.get(0).toString(), ConfigInfo.class);
|
||||
|
||||
Assert.assertEquals(configInfoList.size(), resultList.size());
|
||||
Assert.assertEquals(configInfo.getDataId(), resConfigInfo.getDataId());
|
||||
Assert.assertEquals(configInfo.getGroup(), resConfigInfo.getGroup());
|
||||
Assert.assertEquals(configInfo.getContent(), resConfigInfo.getContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigFuzzyByDetail() throws Exception {
|
||||
List<ConfigInfo> configInfoList = new ArrayList<>();
|
||||
ConfigInfo configInfo = new ConfigInfo("test", "test", "test");
|
||||
configInfoList.add(configInfo);
|
||||
|
||||
Page<ConfigInfo> page = new Page<>();
|
||||
page.setTotalCount(15);
|
||||
page.setPageNumber(1);
|
||||
page.setPagesAvailable(2);
|
||||
page.setPageItems(configInfoList);
|
||||
Map<String, Object> configAdvanceInfo = new HashMap<>(8);
|
||||
configAdvanceInfo.put("content", "server.port");
|
||||
|
||||
when(configInfoPersistService.findConfigInfoLike4Page(1, 10, "test", "test", "", configAdvanceInfo))
|
||||
.thenReturn(page);
|
||||
|
||||
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_V2_PATH + "/searchDetail")
|
||||
.param("search", "blur").param("dataId", "test").param("group", "test")
|
||||
.param("appName", "").param("tenant", "").param("config_tags", "")
|
||||
.param("pageNo", "1").param("pageSize", "10").param("config_detail", "server.port");
|
||||
MockHttpServletResponse response = mockmvc.perform(builder).andReturn().getResponse();
|
||||
String actualValue = response.getContentAsString();
|
||||
|
||||
JsonNode pageItemsNode = JacksonUtils.toObj(actualValue).get("pageItems");
|
||||
List resultList = JacksonUtils.toObj(pageItemsNode.toString(), List.class);
|
||||
ConfigInfo resConfigInfo = JacksonUtils.toObj(pageItemsNode.get(0).toString(), ConfigInfo.class);
|
||||
|
||||
Assert.assertEquals(configInfoList.size(), resultList.size());
|
||||
Assert.assertEquals(configInfo.getDataId(), resConfigInfo.getDataId());
|
||||
Assert.assertEquals(configInfo.getGroup(), resConfigInfo.getGroup());
|
||||
Assert.assertEquals(configInfo.getContent(), resConfigInfo.getContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigAuthFilter() throws Exception {
|
||||
when(authConfigs.isAuthEnabled()).thenReturn(true);
|
||||
|
||||
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_V2_PATH + "/searchDetail")
|
||||
.param("search", "accurate").param("dataId", "test").param("group", "test")
|
||||
.param("appName", "").param("tenant", "").param("config_tags", "")
|
||||
.param("pageNo", "1").param("pageSize", "10").param("config_detail", "server.port");
|
||||
MockHttpServletResponse response = mockmvc.perform(builder).andReturn().getResponse();
|
||||
|
||||
assertEquals(response.getStatus(), HttpServletResponse.SC_FORBIDDEN);
|
||||
assertEquals(response.getErrorMessage(),
|
||||
"Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`"
|
||||
+ " and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`");
|
||||
when(authConfigs.isAuthEnabled()).thenReturn(false);
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ module.exports = Object.assign({}, base, {
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
target: 'http://localhost:8848',
|
||||
pathRewrite: {'^/v1' : '/nacos/v1'}
|
||||
pathRewrite: {'^/v1' : '/nacos/v1', '^/v2' : '/nacos/v2'}
|
||||
}],
|
||||
disableHostCheck: true,
|
||||
open: true,
|
||||
|
@ -302,6 +302,8 @@ const I18N_CONF = {
|
||||
app1: 'Enter App Name\n',
|
||||
tags: 'Tags',
|
||||
pleaseEnterTag: 'Enter Tag',
|
||||
configDetailLabel: 'DetailSearch',
|
||||
configDetailH: 'search config detail',
|
||||
application: 'Application',
|
||||
operation: 'Operation',
|
||||
export: 'Export query results',
|
||||
|
@ -299,6 +299,8 @@ const I18N_CONF = {
|
||||
app1: '请输入应用名',
|
||||
tags: '标签',
|
||||
pleaseEnterTag: '请输入标签',
|
||||
configDetailLabel: '配置项搜索',
|
||||
configDetailH: '搜索具体配置项',
|
||||
application: '归属应用',
|
||||
operation: '操作',
|
||||
export: '导出查询结果',
|
||||
|
@ -44,7 +44,7 @@ import DeleteDialog from 'components/DeleteDialog';
|
||||
import DashboardCard from './DashboardCard';
|
||||
import { getParams, setParams, request } from '@/globalLib';
|
||||
import { connect } from 'react-redux';
|
||||
import { getConfigs } from '../../../reducers/configuration';
|
||||
import { getConfigs, getConfigsV2 } from '../../../reducers/configuration';
|
||||
import PageTitle from '../../../components/PageTitle';
|
||||
import QueryResult from '../../../components/QueryResult';
|
||||
|
||||
@ -58,7 +58,7 @@ const configsTableSelected = new Map();
|
||||
state => ({
|
||||
configurations: state.configuration.configurations,
|
||||
}),
|
||||
{ getConfigs }
|
||||
{ getConfigs, getConfigsV2 }
|
||||
)
|
||||
@ConfigProvider.config
|
||||
class ConfigurationManagement extends React.Component {
|
||||
@ -98,6 +98,7 @@ class ConfigurationManagement extends React.Component {
|
||||
dataId: this.dataId,
|
||||
group: this.group,
|
||||
appName: this.appName,
|
||||
config_detail: getParams('configDetail') || '',
|
||||
config_tags: getParams('configTags') ? getParams('configTags').split(',') : [],
|
||||
tagLst: getParams('tagList') ? getParams('tagList').split(',') : [],
|
||||
selectValue: [],
|
||||
@ -250,7 +251,7 @@ class ConfigurationManagement extends React.Component {
|
||||
params.group = '*' + params.group + '*';
|
||||
}
|
||||
}
|
||||
if (params.dataId.indexOf('*') !== -1 || params.group.indexOf('*') !== -1) {
|
||||
if (this.state.defaultFuzzySearch) {
|
||||
params.search = 'blur';
|
||||
} else {
|
||||
params.search = 'accurate';
|
||||
@ -281,8 +282,18 @@ class ConfigurationManagement extends React.Component {
|
||||
setParams('pageNo', null);
|
||||
this.changeParamsBySearchType(params);
|
||||
this.setState({ loading: true });
|
||||
this.props
|
||||
.getConfigs(params)
|
||||
let props = null;
|
||||
if (this.state.config_detail && this.state.config_detail !== '') {
|
||||
if (this.state.defaultFuzzySearch) {
|
||||
params.config_detail = '*' + this.state.config_detail + '*';
|
||||
} else {
|
||||
params.config_detail = this.state.config_detail;
|
||||
}
|
||||
props = this.props.getConfigsV2(params);
|
||||
} else {
|
||||
props = this.props.getConfigs(params);
|
||||
}
|
||||
props
|
||||
.then(() =>
|
||||
this.setState({
|
||||
loading: false,
|
||||
@ -440,6 +451,13 @@ class ConfigurationManagement extends React.Component {
|
||||
this.setState({ pageSize }, () => this.changePage(1));
|
||||
}
|
||||
|
||||
setConfigDetail(value) {
|
||||
this.setState({
|
||||
config_detail: value,
|
||||
});
|
||||
setParams('configDetail', value);
|
||||
}
|
||||
|
||||
setAppName(value) {
|
||||
this.appName = value;
|
||||
this.setState({
|
||||
@ -530,6 +548,7 @@ class ConfigurationManagement extends React.Component {
|
||||
clear = () => {
|
||||
this.setAppName('');
|
||||
this.setConfigTags([]);
|
||||
this.setConfigDetail('');
|
||||
};
|
||||
|
||||
changeAdvancedQuery = () => {
|
||||
@ -1267,6 +1286,18 @@ class ConfigurationManagement extends React.Component {
|
||||
hasClear
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={this.state.isAdvancedQuery ? {} : { display: 'none' }}
|
||||
label={locale.configDetailLabel}
|
||||
>
|
||||
<Input
|
||||
htmlType={'text'}
|
||||
placeholder={locale.configDetailH}
|
||||
style={{ width: 200 }}
|
||||
value={this.state.config_detail}
|
||||
onChange={this.setConfigDetail.bind(this)}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div style={{ position: 'absolute', right: 10, top: 0 }}>
|
||||
<Icon
|
||||
|
@ -26,6 +26,11 @@ const getConfigs = params => dispatch =>
|
||||
.get('v1/cs/configs', { params })
|
||||
.then(data => dispatch({ type: GET_CONFIGURATION, data }));
|
||||
|
||||
const getConfigsV2 = params => dispatch =>
|
||||
request
|
||||
.get('v2/cs/config/searchDetail', { params })
|
||||
.then(data => dispatch({ type: GET_CONFIGURATION, data }));
|
||||
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case GET_CONFIGURATION:
|
||||
@ -35,4 +40,4 @@ export default (state = initialState, action) => {
|
||||
}
|
||||
};
|
||||
|
||||
export { getConfigs };
|
||||
export { getConfigs, getConfigsV2 };
|
||||
|
@ -35,7 +35,7 @@
|
||||
<link rel="stylesheet" type="text/css" href="console-ui/public/css/icon.css">
|
||||
<link rel="stylesheet" type="text/css" href="console-ui/public/css/font-awesome.css">
|
||||
<!-- 第三方css结束 -->
|
||||
<link href="./css/main.css?19f7f9584ff44dd72eda" rel="stylesheet"></head>
|
||||
<link href="./css/main.css?a8bd622b4e7c17b2a122" rel="stylesheet"></head>
|
||||
|
||||
<body>
|
||||
<div id="root" style="overflow:hidden"></div>
|
||||
@ -56,6 +56,6 @@
|
||||
<script src="console-ui/public/js/merge.js"></script>
|
||||
<script src="console-ui/public/js/loader.js"></script>
|
||||
<!-- 第三方js结束 -->
|
||||
<script type="text/javascript" src="./js/main.js?19f7f9584ff44dd72eda"></script></body>
|
||||
<script type="text/javascript" src="./js/main.js?a8bd622b4e7c17b2a122"></script></body>
|
||||
|
||||
</html>
|
||||
|
File diff suppressed because one or more lines are too long
@ -136,6 +136,7 @@ public class ConfigInfoMapperByDerby extends AbstractMapper implements ConfigInf
|
||||
final String appName = params.get(APP_NAME);
|
||||
final String dataId = params.get(DATA_ID);
|
||||
final String group = params.get(GROUP);
|
||||
final String content = params.get(CONTENT);
|
||||
final String sql = "SELECT id,data_id,group_id,tenant_id,app_name,content,type FROM config_info";
|
||||
StringBuilder where = new StringBuilder(" WHERE ");
|
||||
where.append(" tenant_id=? ");
|
||||
@ -148,6 +149,9 @@ public class ConfigInfoMapperByDerby extends AbstractMapper implements ConfigInf
|
||||
if (StringUtils.isNotBlank(appName)) {
|
||||
where.append(" AND app_name=? ");
|
||||
}
|
||||
if (!StringUtils.isBlank(content)) {
|
||||
where.append(" AND content LIKE ? ");
|
||||
}
|
||||
return sql + where + " OFFSET " + startRow + " ROWS FETCH NEXT " + pageSize + " ROWS ONLY";
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ public class ConfigInfoTagsRelationMapperByDerby extends AbstractMapper implemen
|
||||
final String appName = params.get("appName");
|
||||
final String dataId = params.get("dataId");
|
||||
final String group = params.get("group");
|
||||
final String content = params.get("content");
|
||||
StringBuilder where = new StringBuilder(" WHERE ");
|
||||
final String sql =
|
||||
"SELECT a.id,a.data_id,a.group_id,a.tenant_id,a.app_name,a.content FROM config_info a LEFT JOIN "
|
||||
@ -53,7 +54,9 @@ public class ConfigInfoTagsRelationMapperByDerby extends AbstractMapper implemen
|
||||
if (StringUtils.isNotBlank(appName)) {
|
||||
where.append(" AND a.app_name=? ");
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(content)) {
|
||||
where.append(" AND a.content LIKE ? ");
|
||||
}
|
||||
where.append(" AND b.tag_name IN (");
|
||||
for (int i = 0; i < tagSize; i++) {
|
||||
if (i != 0) {
|
||||
|
@ -144,6 +144,7 @@ public class ConfigInfoMapperByMySql extends AbstractMapper implements ConfigInf
|
||||
final String appName = params.get(APP_NAME);
|
||||
final String dataId = params.get(DATA_ID);
|
||||
final String group = params.get(GROUP);
|
||||
final String content = params.get(CONTENT);
|
||||
final String sql = "SELECT id,data_id,group_id,tenant_id,app_name,content,type,encrypted_data_key FROM config_info";
|
||||
StringBuilder where = new StringBuilder(" WHERE ");
|
||||
where.append(" tenant_id=? ");
|
||||
@ -156,6 +157,9 @@ public class ConfigInfoMapperByMySql extends AbstractMapper implements ConfigInf
|
||||
if (StringUtils.isNotBlank(appName)) {
|
||||
where.append(" AND app_name=? ");
|
||||
}
|
||||
if (!StringUtils.isBlank(content)) {
|
||||
where.append(" AND content LIKE ? ");
|
||||
}
|
||||
return sql + where + " LIMIT " + startRow + "," + pageSize;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ public class ConfigTagsRelationMapperByMySql extends AbstractMapper implements C
|
||||
final String appName = params.get("appName");
|
||||
final String dataId = params.get("dataId");
|
||||
final String group = params.get("group");
|
||||
final String content = params.get("content");
|
||||
StringBuilder where = new StringBuilder(" WHERE ");
|
||||
final String sql =
|
||||
"SELECT a.id,a.data_id,a.group_id,a.tenant_id,a.app_name,a.content FROM config_info a LEFT JOIN "
|
||||
@ -52,7 +53,9 @@ public class ConfigTagsRelationMapperByMySql extends AbstractMapper implements C
|
||||
if (StringUtils.isNotBlank(appName)) {
|
||||
where.append(" AND a.app_name=? ");
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(content)) {
|
||||
where.append(" AND a.content LIKE ? ");
|
||||
}
|
||||
where.append(" AND b.tag_name IN (");
|
||||
for (int i = 0; i < tagSize; i++) {
|
||||
if (i != 0) {
|
||||
|
@ -336,6 +336,7 @@ public interface ConfigInfoMapper extends Mapper {
|
||||
final String appName = params.get(APP_NAME);
|
||||
final String dataId = params.get(DATA_ID);
|
||||
final String group = params.get(GROUP);
|
||||
final String content = params.get(CONTENT);
|
||||
final String sqlCount = "SELECT count(*) FROM config_info";
|
||||
StringBuilder where = new StringBuilder(" WHERE ");
|
||||
where.append(" tenant_id=? ");
|
||||
@ -348,6 +349,9 @@ public interface ConfigInfoMapper extends Mapper {
|
||||
if (StringUtils.isNotBlank(appName)) {
|
||||
where.append(" AND app_name=? ");
|
||||
}
|
||||
if (!StringUtils.isBlank(content)) {
|
||||
where.append(" AND content LIKE ? ");
|
||||
}
|
||||
return sqlCount + where;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ public interface ConfigTagsRelationMapper extends Mapper {
|
||||
final String appName = params.get("appName");
|
||||
final String dataId = params.get("dataId");
|
||||
final String group = params.get("group");
|
||||
final String content = params.get("content");
|
||||
StringBuilder where = new StringBuilder(" WHERE ");
|
||||
final String sqlCount = "SELECT count(*) FROM config_info a LEFT JOIN config_tags_relation b ON a.id=b.id";
|
||||
|
||||
@ -57,7 +58,9 @@ public interface ConfigTagsRelationMapper extends Mapper {
|
||||
if (StringUtils.isNotBlank(appName)) {
|
||||
where.append(" AND a.app_name=? ");
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(content)) {
|
||||
where.append(" AND a.content LIKE ? ");
|
||||
}
|
||||
where.append(" AND b.tag_name IN (");
|
||||
for (int i = 0; i < tagSize; i++) {
|
||||
if (i != 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user