Merge pull request #10475 from alibaba/asoc2022_issue#8460-2
[ISSUE#8460] Add config change hook plugin.
This commit is contained in:
commit
6cde13be92
@ -62,6 +62,11 @@
|
||||
<artifactId>nacos-encryption-plugin</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-config-plugin</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpasyncclient</artifactId>
|
||||
|
@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.aspect;
|
||||
|
||||
import com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;
|
||||
import com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest;
|
||||
import com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse;
|
||||
import com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse;
|
||||
import com.alibaba.nacos.api.remote.request.RequestMeta;
|
||||
import com.alibaba.nacos.api.remote.response.ResponseCode;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.config.server.configuration.ConfigChangeConfigs;
|
||||
import com.alibaba.nacos.config.server.model.SameConfigPolicy;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
import com.alibaba.nacos.config.server.utils.TimeUtils;
|
||||
import com.alibaba.nacos.plugin.config.ConfigChangePluginManager;
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangeConstants;
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangeExecuteTypes;
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
|
||||
import com.alibaba.nacos.plugin.config.model.ConfigChangeRequest;
|
||||
import com.alibaba.nacos.plugin.config.model.ConfigChangeResponse;
|
||||
import com.alibaba.nacos.plugin.config.spi.ConfigChangePluginService;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Config change pointcut aspect,which config change plugin services will pointcut.
|
||||
*
|
||||
* @author liyunfei
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class ConfigChangeAspect {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigChangeAspect.class);
|
||||
|
||||
private static final Integer DEFAULT_BEFORE_QUEUE_CAPACITY = 2;
|
||||
|
||||
private static final Integer DEFAULT_AFTER_QUEUE_CAPACITY = 1;
|
||||
|
||||
private static final String ENABLED = "enabled";
|
||||
|
||||
/**
|
||||
* Publish or update config through http.
|
||||
*/
|
||||
private static final String CLIENT_INTERFACE_PUBLISH_CONFIG =
|
||||
"execution(* com.alibaba.nacos.config.server.controller.ConfigController.publishConfig(..)) "
|
||||
+ "&& args(request,response,dataId,group,tenant,content,tag,appName,srcUser,configTags,desc,use,effect,type,..) "
|
||||
+ "&& @annotation(org.springframework.web.bind.annotation.PostMapping)";
|
||||
|
||||
/**
|
||||
* Publish or update config through rpc.
|
||||
*/
|
||||
private static final String CLIENT_INTERFACE_PUBLISH_CONFIG_RPC =
|
||||
"execution(* com.alibaba.nacos.core.remote.RequestHandler.handleRequest(..)) "
|
||||
+ "&& target(com.alibaba.nacos.config.server.remote.ConfigPublishRequestHandler) "
|
||||
+ "&& args(request,meta)";
|
||||
|
||||
/**
|
||||
* Remove config by id through http.
|
||||
*/
|
||||
private static final String CLIENT_INTERFACE_REMOVE_CONFIG =
|
||||
"execution(* com.alibaba.nacos.config.server.controller.ConfigController.deleteConfig(..))"
|
||||
+ " && args(request,response,dataId,group,tenant,..)";
|
||||
|
||||
/**
|
||||
* Remove config by ids through http.
|
||||
*/
|
||||
private static final String CLIENT_INTERFACE_BATCH_REMOVE_CONFIG =
|
||||
"execution(* com.alibaba.nacos.config.server.controller.ConfigController.deleteConfigs(..))"
|
||||
+ " && args(request,ids)";
|
||||
|
||||
/**
|
||||
* Remove config through rpc.
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:linelength")
|
||||
private static final String CLIENT_INTERFACE_REMOVE_CONFIG_RPC =
|
||||
"execution(* com.alibaba.nacos.core.remote.RequestHandler.handleRequest(..)) "
|
||||
+ " && target(com.alibaba.nacos.config.server.remote.ConfigRemoveRequestHandler)"
|
||||
+ " && args(request,meta)";
|
||||
|
||||
/**
|
||||
* Import file through http.
|
||||
*/
|
||||
private static final String CLIENT_INTERFACE_IMPORT_CONFIG =
|
||||
"execution(* com.alibaba.nacos.config.server.controller.ConfigController.importAndPublishConfig(..)) "
|
||||
+ "&& args(request,srcUser,namespace,policy,file)";
|
||||
|
||||
private final ConfigChangeConfigs configChangeConfigs;
|
||||
|
||||
private ConfigChangePluginManager configChangeManager;
|
||||
|
||||
public ConfigChangeAspect(ConfigChangeConfigs configChangeConfigs) {
|
||||
this.configChangeConfigs = configChangeConfigs;
|
||||
configChangeManager = ConfigChangePluginManager.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish or update config.
|
||||
*/
|
||||
@Around(CLIENT_INTERFACE_PUBLISH_CONFIG)
|
||||
Object publishOrUpdateConfigAround(ProceedingJoinPoint pjp, HttpServletRequest request,
|
||||
HttpServletResponse response, String dataId, String group, String tenant, String content, String tag,
|
||||
String appName, String srcUser, String configTags, String desc, String use, String effect, String type)
|
||||
throws Throwable {
|
||||
final ConfigChangePointCutTypes configChangePointCutType = ConfigChangePointCutTypes.PUBLISH_BY_HTTP;
|
||||
final PriorityQueue<ConfigChangePluginService> pluginServicePriorityQueue = getPluginServicePriorityQueue(
|
||||
configChangePointCutType);
|
||||
// didn't enabled or add relative plugin
|
||||
if (pluginServicePriorityQueue.isEmpty()) {
|
||||
return pjp.proceed();
|
||||
}
|
||||
ConfigChangeRequest configChangeRequest = new ConfigChangeRequest(configChangePointCutType);
|
||||
configChangeRequest.setArg("dataId", dataId);
|
||||
configChangeRequest.setArg("group", group);
|
||||
configChangeRequest.setArg("tenant", tenant);
|
||||
configChangeRequest.setArg("content", content);
|
||||
configChangeRequest.setArg("tag", tag);
|
||||
configChangeRequest.setArg("requestIpApp", appName);
|
||||
configChangeRequest.setArg("srcIp", RequestUtil.getRemoteIp(request));
|
||||
configChangeRequest.setArg("configTags", configTags);
|
||||
configChangeRequest.setArg("desc", desc);
|
||||
configChangeRequest.setArg("use", use);
|
||||
configChangeRequest.setArg("effect", effect);
|
||||
configChangeRequest.setArg("type", type);
|
||||
return configChangeServiceHandle(pjp, pluginServicePriorityQueue, configChangeRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove config.
|
||||
*/
|
||||
@Around(CLIENT_INTERFACE_REMOVE_CONFIG)
|
||||
Object removeConfigByIdAround(ProceedingJoinPoint pjp, HttpServletRequest request, HttpServletResponse response,
|
||||
String dataId, String group, String tenant) throws Throwable {
|
||||
final ConfigChangePointCutTypes configChangePointCutType = ConfigChangePointCutTypes.REMOVE_BY_HTTP;
|
||||
final PriorityQueue<ConfigChangePluginService> pluginServicePriorityQueue = getPluginServicePriorityQueue(
|
||||
configChangePointCutType);
|
||||
// didn't enabled or add relative plugin
|
||||
if (pluginServicePriorityQueue.isEmpty()) {
|
||||
return pjp.proceed();
|
||||
}
|
||||
ConfigChangeRequest configChangeRequest = new ConfigChangeRequest(configChangePointCutType);
|
||||
configChangeRequest.setArg("dataId", dataId);
|
||||
configChangeRequest.setArg("group", group);
|
||||
configChangeRequest.setArg("tenant", tenant);
|
||||
configChangeRequest.setArg("srcIp", RequestUtil.getRemoteIp(request));
|
||||
configChangeRequest.setArg("requestIpApp", RequestUtil.getAppName(request));
|
||||
configChangeRequest.setArg("use", RequestUtil.getSrcUserName(request));
|
||||
return configChangeServiceHandle(pjp, pluginServicePriorityQueue, configChangeRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove config by ids.
|
||||
*/
|
||||
@Around(CLIENT_INTERFACE_BATCH_REMOVE_CONFIG)
|
||||
public Object removeConfigByIdsAround(ProceedingJoinPoint pjp, HttpServletRequest request, List<Long> ids)
|
||||
throws Throwable {
|
||||
final ConfigChangePointCutTypes configChangePointCutType = ConfigChangePointCutTypes.REMOVE_BATCH_HTTP;
|
||||
final PriorityQueue<ConfigChangePluginService> pluginServicePriorityQueue = getPluginServicePriorityQueue(
|
||||
configChangePointCutType);
|
||||
// didn't enabled or add relative plugin
|
||||
if (pluginServicePriorityQueue.isEmpty()) {
|
||||
return pjp.proceed();
|
||||
}
|
||||
ConfigChangeRequest configChangeRequest = new ConfigChangeRequest(configChangePointCutType);
|
||||
configChangeRequest.setArg("dataId", ids.toString());
|
||||
configChangeRequest.setArg("srcIp", RequestUtil.getRemoteIp(request));
|
||||
configChangeRequest.setArg("requestIpApp", RequestUtil.getAppName(request));
|
||||
configChangeRequest.setArg("use", RequestUtil.getSrcUserName(request));
|
||||
return configChangeServiceHandle(pjp, pluginServicePriorityQueue, configChangeRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import config.
|
||||
*/
|
||||
@Around(CLIENT_INTERFACE_IMPORT_CONFIG)
|
||||
public Object importConfigAround(ProceedingJoinPoint pjp, HttpServletRequest request, String srcUser,
|
||||
String namespace, SameConfigPolicy policy, MultipartFile file) throws Throwable {
|
||||
final ConfigChangePointCutTypes configChangePointCutType = ConfigChangePointCutTypes.IMPORT_BY_HTTP;
|
||||
final PriorityQueue<ConfigChangePluginService> pluginServicePriorityQueue = getPluginServicePriorityQueue(
|
||||
configChangePointCutType);
|
||||
// didn't enabled or add relative plugin
|
||||
if (pluginServicePriorityQueue.isEmpty()) {
|
||||
return pjp.proceed();
|
||||
}
|
||||
ConfigChangeRequest configChangeRequest = new ConfigChangeRequest(configChangePointCutType);
|
||||
configChangeRequest.setArg("srcUser", srcUser);
|
||||
configChangeRequest.setArg("namespace", namespace);
|
||||
configChangeRequest.setArg("policy", policy);
|
||||
configChangeRequest.setArg("file", file);
|
||||
configChangeRequest.setArg("srcIp", RequestUtil.getRemoteIp(request));
|
||||
configChangeRequest.setArg("requestIpApp", RequestUtil.getAppName(request));
|
||||
configChangeRequest.setArg("use", RequestUtil.getSrcUserName(request));
|
||||
return configChangeServiceHandle(pjp, pluginServicePriorityQueue, configChangeRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish or update config.
|
||||
*/
|
||||
@Around(CLIENT_INTERFACE_PUBLISH_CONFIG_RPC)
|
||||
Object publishConfigAroundRpc(ProceedingJoinPoint pjp, ConfigPublishRequest request, RequestMeta meta)
|
||||
throws Throwable {
|
||||
final ConfigChangePointCutTypes configChangePointCutType = ConfigChangePointCutTypes.PUBLISH_BY_RPC;
|
||||
final PriorityQueue<ConfigChangePluginService> pluginServicePriorityQueue = getPluginServicePriorityQueue(
|
||||
configChangePointCutType);
|
||||
// didn't enabled or add relative plugin
|
||||
if (pluginServicePriorityQueue.isEmpty()) {
|
||||
return pjp.proceed();
|
||||
}
|
||||
ConfigChangeRequest configChangeRequest = new ConfigChangeRequest(configChangePointCutType);
|
||||
configChangeRequest.setArg("dataId", request.getDataId());
|
||||
configChangeRequest.setArg("group", request.getGroup());
|
||||
configChangeRequest.setArg("tenant", request.getTenant());
|
||||
configChangeRequest.setArg("content", request.getContent());
|
||||
configChangeRequest.setArg("type", request.getAdditionParam("type"));
|
||||
configChangeRequest.setArg("tag", request.getAdditionParam("tag"));
|
||||
configChangeRequest.setArg("configTags", request.getAdditionParam("config_tags"));
|
||||
configChangeRequest.setArg("desc", request.getAdditionParam("desc"));
|
||||
configChangeRequest.setArg("effect", request.getAdditionParam("effect"));
|
||||
configChangeRequest.setArg("appName", request.getAdditionParam("appName"));
|
||||
configChangeRequest.setArg("srcIp", meta.getClientIp());
|
||||
configChangeRequest.setArg("requestIpApp", request.getAdditionParam("requestIpApp"));
|
||||
configChangeRequest.setArg("srcUser", request.getAdditionParam("src_user"));
|
||||
configChangeRequest.setArg("use", request.getAdditionParam("use"));
|
||||
return configChangeServiceHandle(pjp, pluginServicePriorityQueue, configChangeRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove config.
|
||||
*/
|
||||
@Around(CLIENT_INTERFACE_REMOVE_CONFIG_RPC)
|
||||
Object removeConfigAroundRpc(ProceedingJoinPoint pjp, ConfigRemoveRequest request, RequestMeta meta)
|
||||
throws Throwable {
|
||||
final ConfigChangePointCutTypes configChangePointCutType = ConfigChangePointCutTypes.REMOVE_BY_RPC;
|
||||
final PriorityQueue<ConfigChangePluginService> pluginServicePriorityQueue = getPluginServicePriorityQueue(
|
||||
configChangePointCutType);
|
||||
// didn't enabled or add relative plugin
|
||||
if (pluginServicePriorityQueue.isEmpty()) {
|
||||
return pjp.proceed();
|
||||
}
|
||||
ConfigChangeRequest configChangeRequest = new ConfigChangeRequest(configChangePointCutType);
|
||||
configChangeRequest.setArg("dataId", request.getDataId());
|
||||
configChangeRequest.setArg("group", request.getGroup());
|
||||
configChangeRequest.setArg("tenant", request.getTenant());
|
||||
configChangeRequest.setArg("appName", request.getHeader("appName"));
|
||||
configChangeRequest.setArg("srcIp", meta.getClientIp());
|
||||
configChangeRequest.setArg("requestIpApp", request.getHeader("requestIpApp"));
|
||||
configChangeRequest.setArg("srcUser", request.getHeader("src_user"));
|
||||
configChangeRequest.setArg("use", request.getHeader("use"));
|
||||
return configChangeServiceHandle(pjp, pluginServicePriorityQueue, configChangeRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute relevant config change plugin services.
|
||||
*/
|
||||
private Object configChangeServiceHandle(ProceedingJoinPoint pjp,
|
||||
PriorityQueue<ConfigChangePluginService> configChangePluginServicePriorityQueue,
|
||||
ConfigChangeRequest configChangeRequest) {
|
||||
configChangeRequest.setArg("modifyTime", TimeUtils.getCurrentTimeStr());
|
||||
ConfigChangePointCutTypes handleType = configChangeRequest.getRequestType();
|
||||
ConfigChangeResponse configChangeResponse = new ConfigChangeResponse(handleType);
|
||||
// default success,when before plugin service verify failed , set false
|
||||
configChangeResponse.setSuccess(true);
|
||||
PriorityQueue<ConfigChangePluginService> beforeExecutePriorityQueue = new PriorityQueue<>(
|
||||
DEFAULT_BEFORE_QUEUE_CAPACITY, Comparator.comparingInt(ConfigChangePluginService::getOrder));
|
||||
PriorityQueue<ConfigChangePluginService> afterExecutePriorityQueue = new PriorityQueue<>(
|
||||
DEFAULT_AFTER_QUEUE_CAPACITY, Comparator.comparingInt(ConfigChangePluginService::getOrder));
|
||||
|
||||
Object retVal = null;
|
||||
Object[] args = pjp.getArgs();
|
||||
configChangeRequest.setArg(ConfigChangeConstants.ORIGINAL_ARGS, args);
|
||||
|
||||
for (ConfigChangePluginService ccs : configChangePluginServicePriorityQueue) {
|
||||
if (!isEnabled(ccs)) {
|
||||
continue;
|
||||
}
|
||||
if (ConfigChangeExecuteTypes.EXECUTE_BEFORE_TYPE.equals(ccs.executeType())) {
|
||||
beforeExecutePriorityQueue.add(ccs);
|
||||
} else {
|
||||
afterExecutePriorityQueue.add(ccs);
|
||||
}
|
||||
}
|
||||
|
||||
// before plugin service execute
|
||||
for (ConfigChangePluginService ccs : beforeExecutePriorityQueue) {
|
||||
final String serviceType = ccs.getServiceType().toLowerCase(Locale.ROOT);
|
||||
final Properties properties = configChangeConfigs.getPluginProperties(serviceType);
|
||||
configChangeRequest.setArg("pluginProperties", properties);
|
||||
ccs.execute(configChangeRequest, configChangeResponse);
|
||||
if (null != configChangeResponse.getArgs()) {
|
||||
// update args by filter with whitelist
|
||||
args = configChangeResponse.getArgs();
|
||||
}
|
||||
// prevent execute next before plugins service
|
||||
if (!configChangeResponse.isSuccess()) {
|
||||
retVal = wrapErrorResp(configChangeResponse);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// if validate failed,skipped directly
|
||||
if (configChangeResponse.isSuccess()) {
|
||||
retVal = pjp.proceed(args);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LOGGER.warn("config change plugin proceed failed {}", e.getMessage());
|
||||
configChangeResponse.setMsg("config change plugin proceed failed " + e.getMessage());
|
||||
retVal = wrapErrorResp(configChangeResponse);
|
||||
}
|
||||
|
||||
// after plugin service execute
|
||||
ConfigExecutor.executeAsyncConfigChangePluginTask(() -> {
|
||||
for (ConfigChangePluginService ccs : afterExecutePriorityQueue) {
|
||||
try {
|
||||
final String serviceType = ccs.getServiceType().toLowerCase(Locale.ROOT);
|
||||
final Properties properties = configChangeConfigs.getPluginProperties(serviceType);
|
||||
configChangeRequest.setArg(ConfigChangeConstants.PLUGIN_PROPERTIES, properties);
|
||||
ccs.execute(configChangeRequest, configChangeResponse);
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.warn("execute async plugin services failed {}", throwable.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private PriorityQueue<ConfigChangePluginService> getPluginServicePriorityQueue(
|
||||
ConfigChangePointCutTypes configChangePointCutType) {
|
||||
PriorityQueue<ConfigChangePluginService> pluginServicePriorityQueue = ConfigChangePluginManager
|
||||
.findPluginServiceQueueByPointcut(configChangePointCutType);
|
||||
if (pluginServicePriorityQueue == null) {
|
||||
return new PriorityQueue<>();
|
||||
}
|
||||
for (ConfigChangePluginService each : pluginServicePriorityQueue) {
|
||||
if (isEnabled(each)) {
|
||||
return pluginServicePriorityQueue;
|
||||
}
|
||||
}
|
||||
return new PriorityQueue<>();
|
||||
}
|
||||
|
||||
private boolean isEnabled(ConfigChangePluginService configChangePluginService) {
|
||||
Properties serviceConfigProperties = configChangeConfigs
|
||||
.getPluginProperties(configChangePluginService.getServiceType());
|
||||
return Boolean.parseBoolean(serviceConfigProperties.getProperty(ENABLED));
|
||||
}
|
||||
|
||||
private Object wrapErrorResp(ConfigChangeResponse configChangeResponse) {
|
||||
Object retVal = null;
|
||||
switch (configChangeResponse.getResponseType()) {
|
||||
// some of controller did'nt design error msg resp
|
||||
case IMPORT_BY_HTTP:
|
||||
case REMOVE_BATCH_HTTP:
|
||||
case REMOVE_BY_HTTP:
|
||||
case PUBLISH_BY_HTTP: {
|
||||
retVal = RestResultUtils.failed(configChangeResponse.getMsg());
|
||||
break;
|
||||
}
|
||||
case PUBLISH_BY_RPC: {
|
||||
retVal = ConfigPublishResponse
|
||||
.buildFailResponse(ResponseCode.FAIL.getCode(), configChangeResponse.getMsg());
|
||||
break;
|
||||
}
|
||||
case REMOVE_BY_RPC: {
|
||||
retVal = ConfigRemoveResponse.buildFailResponse(configChangeResponse.getMsg());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.configuration;
|
||||
|
||||
import com.alibaba.nacos.common.event.ServerConfigChangeEvent;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangeConstants;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import com.alibaba.nacos.sys.utils.PropertiesUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* config change plugin configs.
|
||||
*
|
||||
* @author liyunfei
|
||||
**/
|
||||
@Configuration
|
||||
public class ConfigChangeConfigs extends Subscriber<ServerConfigChangeEvent> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigChangeConfigs.class);
|
||||
|
||||
private static final String PREFIX = ConfigChangeConstants.NACOS_CORE_CONFIG_PLUGIN_PREFIX;
|
||||
|
||||
private Map<String, Properties> configPluginProperties = new HashMap<>();
|
||||
|
||||
public ConfigChangeConfigs() {
|
||||
NotifyCenter.registerSubscriber(this);
|
||||
refreshPluginProperties();
|
||||
}
|
||||
|
||||
private void refreshPluginProperties() {
|
||||
try {
|
||||
Map<String, Properties> newProperties = new HashMap<>(3);
|
||||
Properties properties = PropertiesUtil.getPropertiesWithPrefix(EnvUtil.getEnvironment(), PREFIX);
|
||||
for (String each : properties.stringPropertyNames()) {
|
||||
int typeIndex = each.indexOf('.');
|
||||
String type = each.substring(0, typeIndex);
|
||||
String subKey = each.substring(typeIndex + 1);
|
||||
newProperties.computeIfAbsent(type, key -> new Properties())
|
||||
.setProperty(subKey, properties.getProperty(each));
|
||||
}
|
||||
configPluginProperties = newProperties;
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("[ConfigChangeConfigs]Refresh config plugin properties failed ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Properties getPluginProperties(String configPluginType) {
|
||||
if (!configPluginProperties.containsKey(configPluginType)) {
|
||||
LOGGER.warn(
|
||||
"[ConfigChangeConfigs]Can't find config plugin properties for type {}, will use empty properties",
|
||||
configPluginType);
|
||||
return new Properties();
|
||||
}
|
||||
return configPluginProperties.get(configPluginType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(ServerConfigChangeEvent event) {
|
||||
refreshPluginProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Event> subscribeType() {
|
||||
return ServerConfigChangeEvent.class;
|
||||
}
|
||||
}
|
@ -475,7 +475,7 @@ public class EmbeddedConfigInfoPersistServiceImpl implements ConfigInfoPersistSe
|
||||
MapperContext context = new MapperContext();
|
||||
context.putWhereParameter(FieldConstant.IDS, paramList);
|
||||
MapperResult result = configInfoMapper.removeConfigInfoByIdsAtomic(context);
|
||||
EmbeddedStorageContextHolder.addSqlContext(result.getSql(), result.getParamList());
|
||||
EmbeddedStorageContextHolder.addSqlContext(result.getSql(), result.getParamList().toArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,6 +46,11 @@ public final class ConfigExecutor {
|
||||
.newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class), 100,
|
||||
new NameThreadFactory("com.alibaba.nacos.config.AsyncNotifyService"));
|
||||
|
||||
private static final ScheduledExecutorService ASYNC_CONFIG_CHANGE_PLUGIN_EXECUTOR = ExecutorFactory.Managed
|
||||
.newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
|
||||
ThreadUtils.getSuitableThreadCount(),
|
||||
new NameThreadFactory("com.alibaba.nacos.config.plugin.AsyncService"));
|
||||
|
||||
private static final ScheduledExecutorService CONFIG_SUB_SERVICE_EXECUTOR = ExecutorFactory.Managed
|
||||
.newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
|
||||
ThreadUtils.getSuitableThreadCount(),
|
||||
@ -76,6 +81,10 @@ public final class ConfigExecutor {
|
||||
ASYNC_NOTIFY_EXECUTOR.schedule(command, delay, unit);
|
||||
}
|
||||
|
||||
public static void executeAsyncConfigChangePluginTask(Runnable runnable) {
|
||||
ASYNC_CONFIG_CHANGE_PLUGIN_EXECUTOR.execute(runnable);
|
||||
}
|
||||
|
||||
public static int asyncNotifyQueueSize() {
|
||||
return ((ScheduledThreadPoolExecutor) ASYNC_NOTIFY_EXECUTOR).getQueue().size();
|
||||
}
|
||||
|
@ -140,6 +140,19 @@ nacos.core.auth.plugin.nacos.token.secret.key=
|
||||
#nacos.core.auth.ldap.filter.prefix=uid
|
||||
#nacos.core.auth.ldap.case.sensitive=true
|
||||
|
||||
#*************** Config Change Plugin Related Configurations ***************#
|
||||
# webhook
|
||||
nacos.core.config.plugin.webhook.enabled=false
|
||||
# It is recommended to use EB https://help.aliyun.com/document_detail/413974.html
|
||||
nacos.core.config.plugin.webhook.url=http://localhost:8080/webhook/send?token=***
|
||||
# The content push max capacity ,byte
|
||||
nacos.core.config.plugin.webhook.contentMaxCapacity=102400
|
||||
# whitelist
|
||||
nacos.core.config.plugin.whitelist.enabled=false
|
||||
# The import file suffixs
|
||||
nacos.core.config.plugin.whitelist.suffixs=xml,text,properties,yaml,html
|
||||
# fileformatcheck,which validate the import file of type and content
|
||||
nacos.core.config.plugin.fileformatcheck.enabled=false
|
||||
|
||||
#*************** Istio Related Configurations ***************#
|
||||
### If turn on the MCP server:
|
||||
|
40
plugin/config/pom.xml
Normal file
40
plugin/config/pom.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 1999-2021 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>nacos-plugin</artifactId>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>nacos-config-plugin</artifactId>
|
||||
<name>nacos-config-plugin ${project.version}</name>
|
||||
<url>http://nacos.io</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-common</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.plugin.config;
|
||||
|
||||
import com.alibaba.nacos.common.spi.NacosServiceLoader;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
|
||||
import com.alibaba.nacos.plugin.config.spi.ConfigChangePluginService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* All config change plugin manager.
|
||||
*
|
||||
* @author liyunfei
|
||||
*/
|
||||
public class ConfigChangePluginManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigChangePluginManager.class);
|
||||
|
||||
private static final Integer PLUGIN_SERVICE_COUNT = 2;
|
||||
|
||||
private static final Integer POINT_CUT_TYPE_COUNT = ConfigChangePointCutTypes.values().length;
|
||||
|
||||
/**
|
||||
* The relationship of serviceType and {@link ConfigChangePluginService} ,default capacity is the count of plugin
|
||||
* service.
|
||||
*/
|
||||
private static final Map<String, ConfigChangePluginService> CONFIG_CHANGE_PLUGIN_SERVICE_MAP = new ConcurrentHashMap<>(
|
||||
PLUGIN_SERVICE_COUNT);
|
||||
|
||||
/**
|
||||
* The relationship of config change pointcut type and the queue of {@link ConfigChangePluginService} will pointcut
|
||||
* it, default capacity is the count of pointcutTypes.
|
||||
*/
|
||||
private static Map<ConfigChangePointCutTypes, PriorityQueue<ConfigChangePluginService>> priorityQueueMap = new ConcurrentHashMap<>(
|
||||
POINT_CUT_TYPE_COUNT);
|
||||
|
||||
private static final ConfigChangePluginManager INSTANCE = new ConfigChangePluginManager();
|
||||
|
||||
private ConfigChangePluginManager() {
|
||||
loadConfigChangeServices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all config change plugin services by spi.
|
||||
*/
|
||||
private static void loadConfigChangeServices() {
|
||||
Collection<ConfigChangePluginService> configChangePluginServices = NacosServiceLoader
|
||||
.load(ConfigChangePluginService.class);
|
||||
// load all config change plugin by spi
|
||||
for (ConfigChangePluginService each : configChangePluginServices) {
|
||||
if (StringUtils.isEmpty(each.getServiceType())) {
|
||||
LOGGER.warn("[ConfigChangePluginManager] Load {}({}) ConfigChangeServiceName(null/empty) fail. "
|
||||
+ "Please Add the Plugin Service ConfigChangeServiceName to resolve.",
|
||||
each.getClass().getName(), each.getClass());
|
||||
continue;
|
||||
}
|
||||
CONFIG_CHANGE_PLUGIN_SERVICE_MAP.put(each.getServiceType(), each);
|
||||
LOGGER.info("[ConfigChangePluginManager] Load {}({}) ConfigChangeServiceName({}) successfully.",
|
||||
each.getClass().getName(), each.getClass(), each.getServiceType());
|
||||
// map the relationship of pointcut and plugin service
|
||||
addPluginServiceByPointCut(each);
|
||||
}
|
||||
}
|
||||
|
||||
public static ConfigChangePluginManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamic get any pluginServiceImpl.
|
||||
*
|
||||
* @param serviceType plugin service type.
|
||||
* @return
|
||||
*/
|
||||
public Optional<ConfigChangePluginService> findPluginServiceImpl(String serviceType) {
|
||||
return Optional.ofNullable(CONFIG_CHANGE_PLUGIN_SERVICE_MAP.get(serviceType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamic add new ConfigChangeService.
|
||||
*
|
||||
* @param configChangePluginService ConfigChangeService.
|
||||
* @return
|
||||
*/
|
||||
public static synchronized boolean join(ConfigChangePluginService configChangePluginService) {
|
||||
CONFIG_CHANGE_PLUGIN_SERVICE_MAP
|
||||
.putIfAbsent(configChangePluginService.getServiceType(), configChangePluginService);
|
||||
addPluginServiceByPointCut(configChangePluginService);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugin service queue of the pointcut method.
|
||||
*
|
||||
* @param pointcutName pointcut method name,detail see {@link ConfigChangePointCutTypes}.
|
||||
* @return
|
||||
*/
|
||||
public static PriorityQueue<ConfigChangePluginService> findPluginServiceQueueByPointcut(
|
||||
ConfigChangePointCutTypes pointcutName) {
|
||||
return priorityQueueMap.getOrDefault(pointcutName, new PriorityQueue<>());
|
||||
}
|
||||
|
||||
private static boolean addPluginServiceByPointCut(ConfigChangePluginService configChangePluginService) {
|
||||
ConfigChangePointCutTypes[] pointcutNames = configChangePluginService.pointcutMethodNames();
|
||||
for (ConfigChangePointCutTypes name : pointcutNames) {
|
||||
PriorityQueue<ConfigChangePluginService> configChangePluginServicePriorityQueue = priorityQueueMap
|
||||
.get(name);
|
||||
if (configChangePluginServicePriorityQueue == null) {
|
||||
configChangePluginServicePriorityQueue = new PriorityQueue<>(PLUGIN_SERVICE_COUNT,
|
||||
Comparator.comparingInt(ConfigChangePluginService::getOrder));
|
||||
}
|
||||
configChangePluginServicePriorityQueue.add(configChangePluginService);
|
||||
priorityQueueMap.put(name, configChangePluginServicePriorityQueue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.plugin.config.constants;
|
||||
|
||||
/**
|
||||
* Config change plugin service constants.
|
||||
*
|
||||
* @author liyunfei
|
||||
*/
|
||||
public class ConfigChangeConstants {
|
||||
|
||||
public static final String NACOS_CORE_CONFIG_PLUGIN_PREFIX = "nacos.core.config.plugin.";
|
||||
|
||||
public static final String PLUGIN_PROPERTIES = "pluginProperties";
|
||||
|
||||
/**
|
||||
* The actual config method args.
|
||||
*/
|
||||
public static final String ORIGINAL_ARGS = "originalArgs";
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.plugin.config.constants;
|
||||
|
||||
/**
|
||||
* ConfigChangeExecuteTypes.
|
||||
*
|
||||
* @author liyunfei
|
||||
*/
|
||||
public enum ConfigChangeExecuteTypes {
|
||||
/**
|
||||
* Execute before pointcut.
|
||||
*/
|
||||
EXECUTE_BEFORE_TYPE,
|
||||
/**
|
||||
* Execute after pointcut.
|
||||
*/
|
||||
EXECUTE_AFTER_TYPE;
|
||||
|
||||
public boolean equals(ConfigChangeExecuteTypes configChangeExecuteTypes) {
|
||||
return this.compareTo(configChangeExecuteTypes) == 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.plugin.config.constants;
|
||||
|
||||
/**
|
||||
* Config change type depend on the pointcut method.
|
||||
*
|
||||
* @author liyunfei
|
||||
*/
|
||||
public enum ConfigChangePointCutTypes {
|
||||
|
||||
/**
|
||||
* Publish or update config through http.
|
||||
*/
|
||||
PUBLISH_BY_HTTP("publishOrUpdateByHttp"),
|
||||
/**
|
||||
* Publish config through rpc.
|
||||
*/
|
||||
PUBLISH_BY_RPC("publishOrUpdateByRpc"),
|
||||
/**
|
||||
* Remove by id through http.
|
||||
*/
|
||||
REMOVE_BY_HTTP("removeSingleByHttp"),
|
||||
/**
|
||||
* Remove through rpc.
|
||||
*/
|
||||
REMOVE_BY_RPC("removeSingleByRpc"),
|
||||
/**
|
||||
* Import config file through http/console.
|
||||
*/
|
||||
IMPORT_BY_HTTP("importFileByHttp"),
|
||||
/**
|
||||
* Remove by ids through http.
|
||||
*/
|
||||
REMOVE_BATCH_HTTP("removeBatchByHttp");
|
||||
|
||||
private final String value;
|
||||
|
||||
ConfigChangePointCutTypes(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean equals(ConfigChangePointCutTypes configChangePointCutTypes) {
|
||||
return this.compareTo(configChangePointCutTypes) == 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.plugin.config.model;
|
||||
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* ConfigChangeRequest.
|
||||
*
|
||||
* @author liyunfei
|
||||
*/
|
||||
public class ConfigChangeRequest {
|
||||
|
||||
private ConfigChangePointCutTypes requestType;
|
||||
|
||||
private HashMap<String, Object> requestArgs = new HashMap<>(8);
|
||||
|
||||
public ConfigChangeRequest(ConfigChangePointCutTypes requestType) {
|
||||
this.requestType = requestType;
|
||||
}
|
||||
|
||||
public ConfigChangePointCutTypes getRequestType() {
|
||||
return requestType;
|
||||
}
|
||||
|
||||
public void setArg(String key, Object value) {
|
||||
requestArgs.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
public Object getArg(String key) {
|
||||
return requestArgs.getOrDefault(key, null);
|
||||
}
|
||||
|
||||
public HashMap<String, Object> getRequestArgs() {
|
||||
return requestArgs;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.plugin.config.model;
|
||||
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
|
||||
|
||||
/**
|
||||
* ConfigChangeResponse.
|
||||
*
|
||||
* @author liyunfei
|
||||
*/
|
||||
public class ConfigChangeResponse {
|
||||
|
||||
private ConfigChangePointCutTypes responseType;
|
||||
|
||||
private boolean isSuccess;
|
||||
|
||||
private Object retVal;
|
||||
|
||||
private String msg;
|
||||
|
||||
private Object[] args;
|
||||
|
||||
public ConfigChangeResponse(ConfigChangePointCutTypes responseType) {
|
||||
this.responseType = responseType;
|
||||
}
|
||||
|
||||
public ConfigChangePointCutTypes getResponseType() {
|
||||
return responseType;
|
||||
}
|
||||
|
||||
public void setResponseType(ConfigChangePointCutTypes responseType) {
|
||||
this.responseType = responseType;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
isSuccess = success;
|
||||
}
|
||||
|
||||
public Object getRetVal() {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void setRetVal(Object retVal) {
|
||||
this.retVal = retVal;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public Object[] getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public void setArgs(Object[] args) {
|
||||
this.args = args;
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.plugin.config.spi;
|
||||
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangeConstants;
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangeExecuteTypes;
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
|
||||
import com.alibaba.nacos.plugin.config.model.ConfigChangeRequest;
|
||||
import com.alibaba.nacos.plugin.config.model.ConfigChangeResponse;
|
||||
|
||||
/**
|
||||
* ConfigChangePluginService.
|
||||
*
|
||||
* @author liyunfei
|
||||
*/
|
||||
public interface ConfigChangePluginService {
|
||||
|
||||
/**
|
||||
* execute config change plugin service.
|
||||
*
|
||||
* @param configChangeRequest ConfigChangeRequest
|
||||
* @param configChangeResponse ConfigChangeResponse
|
||||
*/
|
||||
void execute(ConfigChangeRequest configChangeRequest, ConfigChangeResponse configChangeResponse);
|
||||
|
||||
/**
|
||||
* execute type {@link ConfigChangeExecuteTypes}.
|
||||
*
|
||||
* @return type
|
||||
*/
|
||||
ConfigChangeExecuteTypes executeType();
|
||||
|
||||
|
||||
/**
|
||||
* what kind of plugin service,such as webhook,whiteList and other,need keep a way with the constants config of you
|
||||
* enum in {@link ConfigChangeConstants}.
|
||||
*
|
||||
* @return service type
|
||||
*/
|
||||
String getServiceType();
|
||||
|
||||
/**
|
||||
* when pointcut the same method,according to order to load plugin service. order is lower,prior is higher.
|
||||
*
|
||||
* @return order
|
||||
*/
|
||||
int getOrder();
|
||||
|
||||
/**
|
||||
* the ConfigChangeTypes {@link ConfigChangePointCutTypes} of need to pointcut.
|
||||
*
|
||||
* <p>
|
||||
* ConfigChangeTypes mean the relevant pointcut method.
|
||||
* </p>
|
||||
*
|
||||
* @return array of pointcut the methods
|
||||
*/
|
||||
ConfigChangePointCutTypes[] pointcutMethodNames();
|
||||
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.plugin.config;
|
||||
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangeExecuteTypes;
|
||||
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
|
||||
import com.alibaba.nacos.plugin.config.model.ConfigChangeRequest;
|
||||
import com.alibaba.nacos.plugin.config.model.ConfigChangeResponse;
|
||||
import com.alibaba.nacos.plugin.config.spi.ConfigChangePluginService;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
/**
|
||||
* ConfigChangePluginManagerTests.
|
||||
*
|
||||
* @author liyunfei
|
||||
**/
|
||||
public class ConfigChangePluginManagerTests {
|
||||
@Test
|
||||
public void testInstance() {
|
||||
ConfigChangePluginManager instance = ConfigChangePluginManager.getInstance();
|
||||
Assert.assertNotNull(instance);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void initPluginServices() {
|
||||
ConfigChangePluginManager.join(new ConfigChangePluginService() {
|
||||
@Override
|
||||
public void execute(ConfigChangeRequest configChangeRequest, ConfigChangeResponse configChangeResponse) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigChangeExecuteTypes executeType() {
|
||||
return ConfigChangeExecuteTypes.EXECUTE_BEFORE_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return "test1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigChangePointCutTypes[] pointcutMethodNames() {
|
||||
return new ConfigChangePointCutTypes[]{ConfigChangePointCutTypes.PUBLISH_BY_HTTP, ConfigChangePointCutTypes.PUBLISH_BY_RPC};
|
||||
}
|
||||
});
|
||||
ConfigChangePluginManager.join(new ConfigChangePluginService() {
|
||||
@Override
|
||||
public void execute(ConfigChangeRequest configChangeRequest, ConfigChangeResponse configChangeResponse) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigChangeExecuteTypes executeType() {
|
||||
return ConfigChangeExecuteTypes.EXECUTE_BEFORE_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return "test2";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigChangePointCutTypes[] pointcutMethodNames() {
|
||||
return new ConfigChangePointCutTypes[]{ConfigChangePointCutTypes.IMPORT_BY_HTTP, ConfigChangePointCutTypes.PUBLISH_BY_RPC};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindPluginServiceQueueByPointcut() {
|
||||
PriorityQueue<ConfigChangePluginService> configChangePluginServicePriorityQueue = ConfigChangePluginManager
|
||||
.findPluginServiceQueueByPointcut(ConfigChangePointCutTypes.PUBLISH_BY_HTTP);
|
||||
Assert.assertEquals(1, configChangePluginServicePriorityQueue.size());
|
||||
configChangePluginServicePriorityQueue = ConfigChangePluginManager
|
||||
.findPluginServiceQueueByPointcut(ConfigChangePointCutTypes.PUBLISH_BY_RPC);
|
||||
Assert.assertEquals(2, configChangePluginServicePriorityQueue.size());
|
||||
configChangePluginServicePriorityQueue = ConfigChangePluginManager
|
||||
.findPluginServiceQueueByPointcut(ConfigChangePointCutTypes.IMPORT_BY_HTTP);
|
||||
Assert.assertEquals(1, configChangePluginServicePriorityQueue.size());
|
||||
configChangePluginServicePriorityQueue = ConfigChangePluginManager
|
||||
.findPluginServiceQueueByPointcut(ConfigChangePointCutTypes.REMOVE_BATCH_HTTP);
|
||||
Assert.assertEquals(0, configChangePluginServicePriorityQueue.size());
|
||||
configChangePluginServicePriorityQueue = ConfigChangePluginManager
|
||||
.findPluginServiceQueueByPointcut(ConfigChangePointCutTypes.REMOVE_BY_RPC);
|
||||
Assert.assertEquals(0, configChangePluginServicePriorityQueue.size());
|
||||
configChangePluginServicePriorityQueue = ConfigChangePluginManager
|
||||
.findPluginServiceQueueByPointcut(ConfigChangePointCutTypes.REMOVE_BY_HTTP);
|
||||
Assert.assertEquals(0, configChangePluginServicePriorityQueue.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindPluginServiceByServiceType() {
|
||||
Optional<ConfigChangePluginService> configChangePluginServiceOptional = ConfigChangePluginManager
|
||||
.getInstance().findPluginServiceImpl("test1");
|
||||
Assert.assertTrue(configChangePluginServiceOptional.isPresent());
|
||||
configChangePluginServiceOptional = ConfigChangePluginManager.getInstance().findPluginServiceImpl("test2");
|
||||
Assert.assertTrue(configChangePluginServiceOptional.isPresent());
|
||||
configChangePluginServiceOptional = ConfigChangePluginManager.getInstance().findPluginServiceImpl("test3");
|
||||
Assert.assertFalse(configChangePluginServiceOptional.isPresent());
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@
|
||||
<module>datasource</module>
|
||||
<module>environment</module>
|
||||
<module>control</module>
|
||||
<module>config</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
5
pom.xml
5
pom.xml
@ -734,6 +734,11 @@
|
||||
<artifactId>nacos-encryption-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-config-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-control-plugin</artifactId>
|
||||
|
Loading…
Reference in New Issue
Block a user