[ISSUE #9276] 新增根据配置信息检索内容的功能 (#9925)

* 新增根据配置信息检索内容的功能

* 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:
zhanghong 2023-02-21 10:25:19 +08:00 committed by GitHub
parent 67d5acc892
commit a6332b250d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 513 additions and 20 deletions

View File

@ -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";
}

View File

@ -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";
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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(",");

View File

@ -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(",");

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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',

View File

@ -299,6 +299,8 @@ const I18N_CONF = {
app1: '请输入应用名',
tags: '标签',
pleaseEnterTag: '请输入标签',
configDetailLabel: '配置项搜索',
configDetailH: '搜索具体配置项',
application: '归属应用',
operation: '操作',
export: '导出查询结果',

View File

@ -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

View File

@ -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 };

View File

@ -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

View File

@ -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";
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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) {