Brand new routing rule (#7372)
This commit is contained in:
parent
631aedc5c5
commit
489f4884b7
|
|
@ -14,7 +14,8 @@
|
|||
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/maven-v4_0_0.xsd">
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
|
|
@ -39,7 +40,6 @@
|
|||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
<artifactId>curator-framework</artifactId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.route;
|
||||
|
||||
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
|
||||
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
|
||||
import org.apache.dubbo.common.logger.Logger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.util.VsDestinationGroupRuleDispatcher;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class MeshAppRuleListener implements ConfigurationListener {
|
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(MeshAppRuleListener.class);
|
||||
|
||||
private final VsDestinationGroupRuleDispatcher vsDestinationGroupRuleDispatcher = new VsDestinationGroupRuleDispatcher();
|
||||
|
||||
private String appName;
|
||||
|
||||
private VsDestinationGroup vsDestinationGroupHolder;
|
||||
|
||||
public MeshAppRuleListener(String appName) {
|
||||
this.appName = appName;
|
||||
}
|
||||
|
||||
public void receiveConfigInfo(String configInfo) {
|
||||
logger.info(MessageFormat.format("[MeshAppRule] Received rule for app [{0}]: {1}.",
|
||||
appName, configInfo));
|
||||
try {
|
||||
|
||||
VsDestinationGroup vsDestinationGroup = new VsDestinationGroup();
|
||||
vsDestinationGroup.setAppName(appName);
|
||||
|
||||
Yaml yaml = new Yaml();
|
||||
Yaml yaml2 = new Yaml();
|
||||
Iterable objectIterable = yaml.loadAll(configInfo);
|
||||
for (Object result : objectIterable) {
|
||||
|
||||
Map resultMap = (Map) result;
|
||||
if (resultMap.get("kind").equals("DestinationRule")) {
|
||||
DestinationRule destinationRule = yaml2.loadAs(yaml2.dump(result), DestinationRule.class);
|
||||
vsDestinationGroup.getDestinationRuleList().add(destinationRule);
|
||||
|
||||
} else if (resultMap.get("kind").equals("VirtualService")) {
|
||||
VirtualServiceRule virtualServiceRule = yaml2.loadAs(yaml2.dump(result), VirtualServiceRule.class);
|
||||
vsDestinationGroup.getVirtualServiceRuleList().add(virtualServiceRule);
|
||||
}
|
||||
}
|
||||
|
||||
vsDestinationGroupHolder = vsDestinationGroup;
|
||||
} catch (Exception e) {
|
||||
logger.error("[MeshAppRule] parse failed: " + configInfo, e);
|
||||
}
|
||||
if (vsDestinationGroupHolder != null) {
|
||||
vsDestinationGroupRuleDispatcher.post(vsDestinationGroupHolder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void register(MeshRuleRouter subscriber) {
|
||||
if (vsDestinationGroupHolder != null) {
|
||||
subscriber.onRuleChange(vsDestinationGroupHolder);
|
||||
}
|
||||
vsDestinationGroupRuleDispatcher.register(subscriber);
|
||||
}
|
||||
|
||||
//
|
||||
public void unregister(MeshRuleRouter sub) {
|
||||
vsDestinationGroupRuleDispatcher.unregister(sub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(ConfigChangedEvent event) {
|
||||
receiveConfigInfo(event.getContent());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.route;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.registry.AddressListener;
|
||||
import org.apache.dubbo.rpc.cluster.Directory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Activate(order = 670)
|
||||
public class MeshRuleAddressListenerInterceptor implements AddressListener {
|
||||
|
||||
private static final Object mark = new Object();
|
||||
private static ConcurrentHashMap<String, Object> appMap = new ConcurrentHashMap<String, Object>();
|
||||
|
||||
@Override
|
||||
public List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory) {
|
||||
|
||||
if (addresses != null && !addresses.isEmpty()) {
|
||||
for (URL serviceURL : addresses) {
|
||||
|
||||
String app = serviceURL.getRemoteApplication();
|
||||
if (app != null && !app.isEmpty()) {
|
||||
if (appMap.putIfAbsent(app, mark) == null) {
|
||||
MeshRuleManager.subscribeAppRule(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return addresses;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.route;
|
||||
|
||||
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
|
||||
import org.apache.dubbo.common.logger.Logger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
public final class MeshRuleManager {
|
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(MeshRuleManager.class);
|
||||
|
||||
private static final String MESH_RULE_DATA_ID_SUFFIX = ".MESHAPPRULE";
|
||||
private static final String GROUP = "DEFAULT_GROUP";
|
||||
|
||||
private static ConcurrentHashMap<String, MeshAppRuleListener> appRuleListeners = new ConcurrentHashMap<>();
|
||||
|
||||
public synchronized static void subscribeAppRule(String app) {
|
||||
|
||||
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener(app);
|
||||
String appRuleDataId = app + MESH_RULE_DATA_ID_SUFFIX;
|
||||
DynamicConfiguration configuration = ApplicationModel.getEnvironment().getDynamicConfiguration()
|
||||
.orElse(null);
|
||||
|
||||
if (configuration == null) {
|
||||
logger.warn("Doesn't support DynamicConfiguration!");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String rawConfig = configuration.getConfig(appRuleDataId, GROUP, 5000L);
|
||||
if (rawConfig != null) {
|
||||
meshAppRuleListener.receiveConfigInfo(rawConfig);
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
logger.error("get MeshRuleManager app rule failed.", throwable);
|
||||
}
|
||||
|
||||
configuration.addListener(appRuleDataId, GROUP, meshAppRuleListener);
|
||||
appRuleListeners.put(app, meshAppRuleListener);
|
||||
}
|
||||
|
||||
public static void register(String app, MeshRuleRouter subscriber) {
|
||||
MeshAppRuleListener meshAppRuleListener = appRuleListeners.get(app);
|
||||
if (meshAppRuleListener == null) {
|
||||
logger.warn("appRuleListener can't find when Router register");
|
||||
return;
|
||||
}
|
||||
meshAppRuleListener.register(subscriber);
|
||||
}
|
||||
|
||||
public static void unregister(MeshRuleRouter subscriber) {
|
||||
Collection<MeshAppRuleListener> listeners = appRuleListeners.values();
|
||||
for (MeshAppRuleListener listener : listeners) {
|
||||
listener.unregister(subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.route;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.cluster.Router;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRuleSpec;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.Subset;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboMatchRequest;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboRoute;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.DubboRouteDetail;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceSpec;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboDestination;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboRouteDestination;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.util.VsDestinationGroupRuleListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class MeshRuleRouter implements Router, VsDestinationGroupRuleListener {
|
||||
|
||||
protected int priority = -500;
|
||||
protected boolean force = false;
|
||||
protected URL url;
|
||||
|
||||
private VsDestinationGroup vsDestinationGroup;
|
||||
|
||||
private Map<String, String> sourcesLables = new HashMap<>();
|
||||
|
||||
protected List<Invoker<?>> invokerList = new ArrayList<>();
|
||||
|
||||
Map<String, List<Invoker<?>>> subsetMap;
|
||||
|
||||
private String remoteAppName;
|
||||
|
||||
public MeshRuleRouter(URL url) {
|
||||
this.url = url;
|
||||
sourcesLables.putAll(url.getParameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
|
||||
|
||||
List<DubboRouteDestination> routeDestination = getDubboRouteDestination(invocation);
|
||||
|
||||
if (routeDestination == null) {
|
||||
return invokers;
|
||||
} else {
|
||||
Random random = new Random();
|
||||
int index = random.nextInt(routeDestination.size());
|
||||
DubboRouteDestination dubboRouteDestination = routeDestination.get(index);
|
||||
|
||||
DubboDestination dubboDestination = dubboRouteDestination.getDestination();
|
||||
|
||||
String host = dubboDestination.getHost();
|
||||
String subset = dubboDestination.getSubset();
|
||||
|
||||
List<Invoker<?>> result;
|
||||
|
||||
Map<String, List<Invoker<?>>> subsetMapCopy = this.subsetMap;
|
||||
|
||||
//TODO make intersection with invokers
|
||||
if (subsetMapCopy != null) {
|
||||
|
||||
do {
|
||||
result = subsetMapCopy.get(subset);
|
||||
|
||||
if (result != null && result.size() > 0) {
|
||||
return (List) result;
|
||||
}
|
||||
|
||||
dubboRouteDestination = dubboDestination.getFallback();
|
||||
if (dubboRouteDestination == null) {
|
||||
break;
|
||||
}
|
||||
dubboDestination = dubboRouteDestination.getDestination();
|
||||
|
||||
host = dubboDestination.getHost();
|
||||
subset = dubboDestination.getSubset();
|
||||
} while (true);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return invokers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void notify(List<Invoker<T>> invokers) {
|
||||
List invokerList = invokers == null ? Collections.emptyList() : invokers;
|
||||
this.invokerList = invokerList;
|
||||
registerAppRule(invokerList);
|
||||
computeSubset();
|
||||
}
|
||||
|
||||
|
||||
private void registerAppRule(List<Invoker<?>> invokers) {
|
||||
if (StringUtils.isEmpty(remoteAppName)) {
|
||||
synchronized (this) {
|
||||
if (StringUtils.isEmpty(remoteAppName) && invokers != null && invokers.size() > 0) {
|
||||
for (Invoker invoker : invokers) {
|
||||
String applicationName = invoker.getUrl().getRemoteApplication();
|
||||
if (StringUtils.isNotEmpty(applicationName) && !"unknown".equals(applicationName)) {
|
||||
remoteAppName = applicationName;
|
||||
MeshRuleManager.register(remoteAppName, this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onRuleChange(VsDestinationGroup vsDestinationGroup) {
|
||||
this.vsDestinationGroup = vsDestinationGroup;
|
||||
computeSubset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRuntime() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForce() {
|
||||
return force;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
private List<DubboRouteDestination> getDubboRouteDestination(Invocation invocation) {
|
||||
|
||||
if (vsDestinationGroup != null) {
|
||||
|
||||
List<VirtualServiceRule> virtualServiceRuleList = vsDestinationGroup.getVirtualServiceRuleList();
|
||||
if (virtualServiceRuleList.size() > 0) {
|
||||
for (VirtualServiceRule virtualServiceRule : virtualServiceRuleList) {
|
||||
DubboRoute dubboRoute = getDubboRoute(virtualServiceRule, invocation);
|
||||
if (dubboRoute != null) {
|
||||
return getDubboRouteDestination(dubboRoute, invocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected DubboRoute getDubboRoute(VirtualServiceRule virtualServiceRule, Invocation invocation) {
|
||||
String serviceName = invocation.getServiceName();
|
||||
|
||||
VirtualServiceSpec spec = virtualServiceRule.getSpec();
|
||||
List<DubboRoute> dubboRouteList = spec.getDubbo();
|
||||
if (dubboRouteList.size() > 0) {
|
||||
for (DubboRoute dubboRoute : dubboRouteList) {
|
||||
List<StringMatch> stringMatchList = dubboRoute.getServices();
|
||||
if (stringMatchList == null || stringMatchList.size() == 0) {
|
||||
return dubboRoute;
|
||||
}
|
||||
for (StringMatch stringMatch : stringMatchList) {
|
||||
if (StringMatch.isMatch(stringMatch, serviceName)) {
|
||||
return dubboRoute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected List<DubboRouteDestination> getDubboRouteDestination(DubboRoute dubboRoute, Invocation invocation) {
|
||||
|
||||
List<DubboRouteDetail> dubboRouteDetailList = dubboRoute.getRoutedetail();
|
||||
if (dubboRouteDetailList.size() > 0) {
|
||||
DubboRouteDetail dubboRouteDetail = findMatchDubboRouteDetail(dubboRouteDetailList, invocation);
|
||||
if (dubboRouteDetail != null) {
|
||||
return dubboRouteDetail.getRoute();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected DubboRouteDetail findMatchDubboRouteDetail(List<DubboRouteDetail> dubboRouteDetailList, Invocation invocation) {
|
||||
|
||||
String methodName = invocation.getMethodName();
|
||||
String[] parameterTypeList = invocation.getCompatibleParamSignatures();
|
||||
Object[] parameters = invocation.getArguments();
|
||||
|
||||
|
||||
for (DubboRouteDetail dubboRouteDetail : dubboRouteDetailList) {
|
||||
List<DubboMatchRequest> matchRequestList = dubboRouteDetail.getMatch();
|
||||
if (matchRequestList == null || matchRequestList.size() == 0) {
|
||||
return dubboRouteDetail;
|
||||
}
|
||||
|
||||
boolean match = true;
|
||||
|
||||
//FIXME to deal with headers
|
||||
for (DubboMatchRequest dubboMatchRequest : matchRequestList) {
|
||||
if (!DubboMatchRequest.isMatch(dubboMatchRequest, methodName, parameterTypeList, parameters,
|
||||
sourcesLables,
|
||||
new HashMap<>(), invocation.getAttachments(),
|
||||
new HashMap<>())) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
return dubboRouteDetail;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected synchronized void computeSubset() {
|
||||
if (invokerList == null || invokerList.size() == 0) {
|
||||
this.subsetMap = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vsDestinationGroup == null) {
|
||||
this.subsetMap = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, List<Invoker<?>>> subsetMap = computeSubsetMap(invokerList, vsDestinationGroup.getDestinationRuleList());
|
||||
|
||||
if (subsetMap.size() == 0) {
|
||||
this.subsetMap = null;
|
||||
} else {
|
||||
this.subsetMap = subsetMap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Map<String, List<Invoker<?>>> computeSubsetMap(List<Invoker<?>> invokers, List<DestinationRule> destinationRules) {
|
||||
Map<String, List<Invoker<?>>> subsetMap = new HashMap<>();
|
||||
|
||||
for (DestinationRule destinationRule : destinationRules) {
|
||||
DestinationRuleSpec destinationRuleSpec = destinationRule.getSpec();
|
||||
String host = destinationRuleSpec.getHost();
|
||||
List<Subset> subsetList = destinationRuleSpec.getSubsets();
|
||||
|
||||
for (Subset subset : subsetList) {
|
||||
String subsetName = subset.getName();
|
||||
List<Invoker<?>> subsetInvokerList = new ArrayList<>();
|
||||
subsetMap.put(subsetName, subsetInvokerList);
|
||||
|
||||
Map<String, String> labels = subset.getLabels();
|
||||
|
||||
for (Invoker<?> invoker : invokers) {
|
||||
Map<String, String> parameters = invoker.getUrl().getParameters();
|
||||
if (containMapKeyValue(parameters, labels)) {
|
||||
subsetInvokerList.add(invoker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return subsetMap;
|
||||
}
|
||||
|
||||
|
||||
protected boolean containMapKeyValue(Map<String, String> originMap, Map<String, String> inputMap) {
|
||||
if (inputMap == null || inputMap.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : inputMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
|
||||
String originMapValue = originMap.get(key);
|
||||
if (!value.equals(originMapValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// just for test
|
||||
protected void setVsDestinationGroup(VsDestinationGroup vsDestinationGroup) {
|
||||
this.vsDestinationGroup = vsDestinationGroup;
|
||||
}
|
||||
|
||||
// just for test
|
||||
protected void setSourcesLables(Map<String, String> sourcesLables) {
|
||||
this.sourcesLables = sourcesLables;
|
||||
}
|
||||
|
||||
// just for test
|
||||
protected void setInvokerList(List<Invoker<?>> invokerList) {
|
||||
this.invokerList = invokerList;
|
||||
}
|
||||
|
||||
// just for test
|
||||
protected void setSubsetMap(Map<String, List<Invoker<?>>> subsetMap) {
|
||||
this.subsetMap = subsetMap;
|
||||
}
|
||||
|
||||
|
||||
public VsDestinationGroup getVsDestinationGroup() {
|
||||
return vsDestinationGroup;
|
||||
}
|
||||
|
||||
public Map<String, String> getSourcesLables() {
|
||||
return sourcesLables;
|
||||
}
|
||||
|
||||
public List<Invoker<?>> getInvokerList() {
|
||||
return invokerList;
|
||||
}
|
||||
|
||||
public Map<String, List<Invoker<?>>> getSubsetMap() {
|
||||
return subsetMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.route;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.rpc.cluster.Router;
|
||||
import org.apache.dubbo.rpc.cluster.RouterFactory;
|
||||
|
||||
|
||||
@Activate(order = -50)
|
||||
public class MeshRuleRouterFactory implements RouterFactory {
|
||||
@Override
|
||||
public Router getRouter(URL url) {
|
||||
return new MeshRuleRouter(url);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class BaseRule {
|
||||
private String apiVersion;
|
||||
private String kind;
|
||||
private Map<String,String> metadata;
|
||||
|
||||
public String getApiVersion() {
|
||||
return apiVersion;
|
||||
}
|
||||
|
||||
public void setApiVersion(String apiVersion) {
|
||||
this.apiVersion = apiVersion;
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
public void setKind(String kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public Map<String, String> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Map<String, String> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BaseRule{" +
|
||||
"apiVersion='" + apiVersion + '\'' +
|
||||
", kind='" + kind + '\'' +
|
||||
", metadata=" + metadata +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class VsDestinationGroup {
|
||||
private String appName;
|
||||
private List<VirtualServiceRule> virtualServiceRuleList = new ArrayList<>();
|
||||
private List<DestinationRule> destinationRuleList = new ArrayList<>();
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public void setAppName(String appName) {
|
||||
this.appName = appName;
|
||||
}
|
||||
|
||||
public List<VirtualServiceRule> getVirtualServiceRuleList() {
|
||||
return virtualServiceRuleList;
|
||||
}
|
||||
|
||||
public void setVirtualServiceRuleList(List<VirtualServiceRule> virtualServiceRuleList) {
|
||||
this.virtualServiceRuleList = virtualServiceRuleList;
|
||||
}
|
||||
|
||||
public List<DestinationRule> getDestinationRuleList() {
|
||||
return destinationRuleList;
|
||||
}
|
||||
|
||||
public void setDestinationRuleList(List<DestinationRule> destinationRuleList) {
|
||||
this.destinationRuleList = destinationRuleList;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
|
||||
|
||||
|
||||
public class ConnectionPoolSettings {
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule;
|
||||
|
||||
|
||||
public class DestinationRule extends BaseRule {
|
||||
private DestinationRuleSpec spec;
|
||||
|
||||
public DestinationRuleSpec getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
public void setSpec(DestinationRuleSpec spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DestinationRule{" +
|
||||
"base=" + super.toString() +
|
||||
", spec=" + spec +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class DestinationRuleSpec {
|
||||
private String host;
|
||||
private List<Subset> subsets;
|
||||
private TrafficPolicy trafficPolicy;
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public List<Subset> getSubsets() {
|
||||
return subsets;
|
||||
}
|
||||
|
||||
public void setSubsets(List<Subset> subsets) {
|
||||
this.subsets = subsets;
|
||||
}
|
||||
|
||||
public TrafficPolicy getTrafficPolicy() {
|
||||
return trafficPolicy;
|
||||
}
|
||||
|
||||
public void setTrafficPolicy(TrafficPolicy trafficPolicy) {
|
||||
this.trafficPolicy = trafficPolicy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DestinationRuleSpec{" +
|
||||
"host='" + host + '\'' +
|
||||
", subsets=" + subsets +
|
||||
", trafficPolicy=" + trafficPolicy +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class Subset {
|
||||
private String name;
|
||||
private Map<String, String> labels;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Map<String, String> getLabels() {
|
||||
return labels;
|
||||
}
|
||||
|
||||
public void setLabels(Map<String, String> labels) {
|
||||
this.labels = labels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Subset{" +
|
||||
"name='" + name + '\'' +
|
||||
", labels=" + labels +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
|
||||
|
||||
|
||||
public class TCPSettings {
|
||||
private int maxConnections;
|
||||
private int connectTimeout;
|
||||
private TcpKeepalive tcpKeepalive;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
|
||||
|
||||
|
||||
public class TcpKeepalive {
|
||||
private int probes;
|
||||
private int time;
|
||||
private int interval;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance.LoadBalancerSettings;
|
||||
|
||||
|
||||
public class TrafficPolicy {
|
||||
private LoadBalancerSettings loadBalancer;
|
||||
|
||||
public LoadBalancerSettings getLoadBalancer() {
|
||||
return loadBalancer;
|
||||
}
|
||||
|
||||
public void setLoadBalancer(LoadBalancerSettings loadBalancer) {
|
||||
this.loadBalancer = loadBalancer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TrafficPolicy{" +
|
||||
"loadBalancer=" + loadBalancer +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance;
|
||||
|
||||
|
||||
public class ConsistentHashLB {
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance;
|
||||
|
||||
|
||||
public class LoadBalancerSettings {
|
||||
private SimpleLB simple;
|
||||
private ConsistentHashLB consistentHash;
|
||||
|
||||
public SimpleLB getSimple() {
|
||||
return simple;
|
||||
}
|
||||
|
||||
public void setSimple(SimpleLB simple) {
|
||||
this.simple = simple;
|
||||
}
|
||||
|
||||
public ConsistentHashLB getConsistentHash() {
|
||||
return consistentHash;
|
||||
}
|
||||
|
||||
public void setConsistentHash(ConsistentHashLB consistentHash) {
|
||||
this.consistentHash = consistentHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoadBalancerSettings{" +
|
||||
"simple=" + simple +
|
||||
", consistentHash=" + consistentHash +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance;
|
||||
|
||||
|
||||
public enum SimpleLB {
|
||||
ROUND_ROBIN,
|
||||
LEAST_CONN,
|
||||
RANDOM,
|
||||
PASSTHROUGH
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DoubleMatch;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DubboAttachmentMatch;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DubboMethodMatch;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class DubboMatchRequest {
|
||||
private String name;
|
||||
private DubboMethodMatch method;
|
||||
private Map<String, String> sourceLabels;
|
||||
private DubboAttachmentMatch attachments;
|
||||
private Map<String, StringMatch> headers;
|
||||
private DoubleMatch threshold;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public DubboMethodMatch getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(DubboMethodMatch method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public Map<String, String> getSourceLabels() {
|
||||
return sourceLabels;
|
||||
}
|
||||
|
||||
public void setSourceLabels(Map<String, String> sourceLabels) {
|
||||
this.sourceLabels = sourceLabels;
|
||||
}
|
||||
|
||||
public DubboAttachmentMatch getAttachments() {
|
||||
return attachments;
|
||||
}
|
||||
|
||||
public void setAttachments(DubboAttachmentMatch attachments) {
|
||||
this.attachments = attachments;
|
||||
}
|
||||
|
||||
public Map<String, StringMatch> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public void setHeaders(Map<String, StringMatch> headers) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
public DoubleMatch getThreshold() {
|
||||
return threshold;
|
||||
}
|
||||
|
||||
public void setThreshold(DoubleMatch threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMatch(DubboMatchRequest dubboMatchRequest,
|
||||
String methodName, String[] parameterTypeList, Object[] parameters,
|
||||
Map<String, String> sourceLabels,
|
||||
Map<String, String> eagleeyeContext, Map<String, String> dubboContext,
|
||||
Map<String, String> headers
|
||||
) {
|
||||
if (dubboMatchRequest.getMethod() != null) {
|
||||
if (!DubboMethodMatch.isMatch(dubboMatchRequest.getMethod(), methodName, parameterTypeList, parameters)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dubboMatchRequest.getSourceLabels() != null) {
|
||||
for (Map.Entry<String, String> entry : dubboMatchRequest.getSourceLabels().entrySet()) {
|
||||
String value = sourceLabels.get(entry.getKey());
|
||||
if (value == null || !entry.getValue().equals(value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dubboMatchRequest.getAttachments() != null) {
|
||||
if (!DubboAttachmentMatch.isMatch(dubboMatchRequest.getAttachments(),eagleeyeContext,dubboContext)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO headers
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DubboMatchRequest{" +
|
||||
"name='" + name + '\'' +
|
||||
", method=" + method +
|
||||
", sourceLabels=" + sourceLabels +
|
||||
", attachments=" + attachments +
|
||||
", headers=" + headers +
|
||||
", threshold=" + threshold +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class DubboRoute {
|
||||
private String name;
|
||||
private List<StringMatch> services;
|
||||
private List<DubboRouteDetail> routedetail;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<StringMatch> getServices() {
|
||||
return services;
|
||||
}
|
||||
|
||||
public void setServices(List<StringMatch> services) {
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
public List<DubboRouteDetail> getRoutedetail() {
|
||||
return routedetail;
|
||||
}
|
||||
|
||||
public void setRoutedetail(List<DubboRouteDetail> routedetail) {
|
||||
this.routedetail = routedetail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DubboRoute{" +
|
||||
"name='" + name + '\'' +
|
||||
", services=" + services +
|
||||
", routedetail=" + routedetail +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboRouteDestination;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class DubboRouteDetail {
|
||||
private String name;
|
||||
private List<DubboMatchRequest> match;
|
||||
private List<DubboRouteDestination> route;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<DubboMatchRequest> getMatch() {
|
||||
return match;
|
||||
}
|
||||
|
||||
public void setMatch(List<DubboMatchRequest> match) {
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
public List<DubboRouteDestination> getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
public void setRoute(List<DubboRouteDestination> route) {
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DubboRouteDetail{" +
|
||||
"name='" + name + '\'' +
|
||||
", match=" + match +
|
||||
", route=" + route +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule;
|
||||
|
||||
|
||||
public class VirtualServiceRule extends BaseRule {
|
||||
private VirtualServiceSpec spec;
|
||||
|
||||
public VirtualServiceSpec getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
public void setSpec(VirtualServiceSpec spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VirtualServiceRule{" +
|
||||
"base=" + super.toString() +
|
||||
", spec=" + spec +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class VirtualServiceSpec {
|
||||
private List<String> hosts;
|
||||
private List<DubboRoute> dubbo;
|
||||
|
||||
public List<String> getHosts() {
|
||||
return hosts;
|
||||
}
|
||||
|
||||
public void setHosts(List<String> hosts) {
|
||||
this.hosts = hosts;
|
||||
}
|
||||
|
||||
public List<DubboRoute> getDubbo() {
|
||||
return dubbo;
|
||||
}
|
||||
|
||||
public void setDubbo(List<DubboRoute> dubbo) {
|
||||
this.dubbo = dubbo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VirtualServiceSpec{" +
|
||||
"hosts=" + hosts +
|
||||
", dubbo=" + dubbo +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination;
|
||||
|
||||
|
||||
public class DubboDestination {
|
||||
private String host;
|
||||
private String subset;
|
||||
private int port;
|
||||
private DubboRouteDestination fallback;
|
||||
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public String getSubset() {
|
||||
return subset;
|
||||
}
|
||||
|
||||
public void setSubset(String subset) {
|
||||
this.subset = subset;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public DubboRouteDestination getFallback() {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
public void setFallback(DubboRouteDestination fallback) {
|
||||
this.fallback = fallback;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination;
|
||||
|
||||
|
||||
public class DubboRouteDestination {
|
||||
private DubboDestination destination;
|
||||
private int weight;
|
||||
|
||||
public DubboDestination getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public void setDestination(DubboDestination destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public void setWeight(int weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
public class BoolMatch {
|
||||
private Boolean exact;
|
||||
|
||||
public Boolean getExact() {
|
||||
return exact;
|
||||
}
|
||||
|
||||
public void setExact(Boolean exact) {
|
||||
this.exact = exact;
|
||||
}
|
||||
|
||||
public static boolean isMatch(BoolMatch boolMatch,boolean input){
|
||||
if (boolMatch.getExact() != null){
|
||||
return input == boolMatch.getExact();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
public class DoubleMatch {
|
||||
private Double exact;
|
||||
private DoubleRangeMatch range;
|
||||
private Double mod;
|
||||
|
||||
public Double getExact() {
|
||||
return exact;
|
||||
}
|
||||
|
||||
public void setExact(Double exact) {
|
||||
this.exact = exact;
|
||||
}
|
||||
|
||||
public DoubleRangeMatch getRange() {
|
||||
return range;
|
||||
}
|
||||
|
||||
public void setRange(DoubleRangeMatch range) {
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
public Double getMod() {
|
||||
return mod;
|
||||
}
|
||||
|
||||
public void setMod(Double mod) {
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMatch(DoubleMatch doubleMatch, Double input) {
|
||||
if (doubleMatch.getExact() != null && doubleMatch.getMod() == null) {
|
||||
return input.equals(doubleMatch.getExact());
|
||||
} else if (doubleMatch.getRange() != null) {
|
||||
return DoubleRangeMatch.isMatch(doubleMatch.getRange(), input);
|
||||
} else if (doubleMatch.getExact() != null && doubleMatch.getMod() != null) {
|
||||
Double result = input % doubleMatch.getMod();
|
||||
return result.equals(doubleMatch.getExact());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
public class DoubleRangeMatch {
|
||||
private Double start;
|
||||
private Double end;
|
||||
|
||||
public Double getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(Double start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public Double getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(Double end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMatch(DoubleRangeMatch doubleRangeMatch, Double input) {
|
||||
if (doubleRangeMatch.getStart() != null && doubleRangeMatch.getEnd() != null) {
|
||||
return input.compareTo(doubleRangeMatch.getStart()) >= 0 && input.compareTo(doubleRangeMatch.getEnd()) < 0;
|
||||
} else if (doubleRangeMatch.getStart() != null) {
|
||||
return input.compareTo(doubleRangeMatch.getStart()) >= 0;
|
||||
} else if (doubleRangeMatch.getEnd() != null) {
|
||||
return input.compareTo(doubleRangeMatch.getEnd()) < 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class DubboAttachmentMatch {
|
||||
private Map<String, StringMatch> eagleeyecontext;
|
||||
private Map<String, StringMatch> dubbocontext;
|
||||
|
||||
public Map<String, StringMatch> getEagleeyecontext() {
|
||||
return eagleeyecontext;
|
||||
}
|
||||
|
||||
public void setEagleeyecontext(Map<String, StringMatch> eagleeyecontext) {
|
||||
this.eagleeyecontext = eagleeyecontext;
|
||||
}
|
||||
|
||||
public Map<String, StringMatch> getDubbocontext() {
|
||||
return dubbocontext;
|
||||
}
|
||||
|
||||
public void setDubbocontext(Map<String, StringMatch> dubbocontext) {
|
||||
this.dubbocontext = dubbocontext;
|
||||
}
|
||||
|
||||
public static boolean isMatch(DubboAttachmentMatch dubboAttachmentMatch, Map<String, String> eagleeyeContext, Map<String, String> dubboContext) {
|
||||
if (dubboAttachmentMatch.getDubbocontext() != null) {
|
||||
for (Map.Entry<String, StringMatch> stringStringMatchEntry : dubboAttachmentMatch.getDubbocontext().entrySet()) {
|
||||
String key = stringStringMatchEntry.getKey();
|
||||
StringMatch stringMatch = stringStringMatchEntry.getValue();
|
||||
|
||||
String dubboContextValue = dubboContext.get(key);
|
||||
if (dubboContextValue == null) {
|
||||
return false;
|
||||
}
|
||||
if (!StringMatch.isMatch(stringMatch, dubboContextValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dubboAttachmentMatch.getEagleeyecontext() != null) {
|
||||
for (Map.Entry<String, StringMatch> stringStringMatchEntry : dubboAttachmentMatch.getEagleeyecontext().entrySet()) {
|
||||
String key = stringStringMatchEntry.getKey();
|
||||
StringMatch stringMatch = stringStringMatchEntry.getValue();
|
||||
|
||||
String eagleeyeContextValue = eagleeyeContext.get(key);
|
||||
if (eagleeyeContextValue == null) {
|
||||
return false;
|
||||
}
|
||||
if (!StringMatch.isMatch(stringMatch, eagleeyeContextValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
public class DubboMethodArg {
|
||||
private int index;
|
||||
private String type;
|
||||
private ListStringMatch str_value;
|
||||
private ListDoubleMatch num_value;
|
||||
private BoolMatch bool_value;
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public ListStringMatch getStr_value() {
|
||||
return str_value;
|
||||
}
|
||||
|
||||
public void setStr_value(ListStringMatch str_value) {
|
||||
this.str_value = str_value;
|
||||
}
|
||||
|
||||
public ListDoubleMatch getNum_value() {
|
||||
return num_value;
|
||||
}
|
||||
|
||||
public void setNum_value(ListDoubleMatch num_value) {
|
||||
this.num_value = num_value;
|
||||
}
|
||||
|
||||
public BoolMatch getBool_value() {
|
||||
return bool_value;
|
||||
}
|
||||
|
||||
public void setBool_value(BoolMatch bool_value) {
|
||||
this.bool_value = bool_value;
|
||||
}
|
||||
|
||||
public static boolean isMatch(DubboMethodArg dubboMethodArg, Object input) {
|
||||
|
||||
if (dubboMethodArg.getStr_value() != null) {
|
||||
return ListStringMatch.isMatch(dubboMethodArg.getStr_value(), (String) input);
|
||||
} else if (dubboMethodArg.getNum_value() != null) {
|
||||
return ListDoubleMatch.isMatch(dubboMethodArg.getNum_value(), Double.valueOf(input.toString()));
|
||||
} else if (dubboMethodArg.getBool_value() != null) {
|
||||
return BoolMatch.isMatch(dubboMethodArg.getBool_value(), (Boolean) input);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DubboMethodArg{" +
|
||||
"index=" + index +
|
||||
", type='" + type + '\'' +
|
||||
", str_value=" + str_value +
|
||||
", num_value=" + num_value +
|
||||
", bool_value=" + bool_value +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class DubboMethodMatch {
|
||||
private StringMatch name_match;
|
||||
private Integer argc;
|
||||
private List<DubboMethodArg> args;
|
||||
private List<StringMatch> argp;
|
||||
private Map<String, StringMatch> headers;
|
||||
|
||||
public StringMatch getName_match() {
|
||||
return name_match;
|
||||
}
|
||||
|
||||
public void setName_match(StringMatch name_match) {
|
||||
this.name_match = name_match;
|
||||
}
|
||||
|
||||
public Integer getArgc() {
|
||||
return argc;
|
||||
}
|
||||
|
||||
public void setArgc(Integer argc) {
|
||||
this.argc = argc;
|
||||
}
|
||||
|
||||
public List<DubboMethodArg> getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public void setArgs(List<DubboMethodArg> args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public List<StringMatch> getArgp() {
|
||||
return argp;
|
||||
}
|
||||
|
||||
public void setArgp(List<StringMatch> argp) {
|
||||
this.argp = argp;
|
||||
}
|
||||
|
||||
public Map<String, StringMatch> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public void setHeaders(Map<String, StringMatch> headers) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
public static boolean isMatch(DubboMethodMatch dubboMethodMatch, String methodName, String[] parameterTypeList, Object[] parameters) {
|
||||
StringMatch nameMatch = dubboMethodMatch.getName_match();
|
||||
if (nameMatch != null && !StringMatch.isMatch(nameMatch, methodName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Integer argc = dubboMethodMatch.getArgc();
|
||||
if (argc != null &&
|
||||
((argc != 0 && (parameters == null || parameters.length == 0)) || (argc != parameters.length))) {
|
||||
return false;
|
||||
}
|
||||
List<StringMatch> argp = dubboMethodMatch.getArgp();
|
||||
if (argp != null) {
|
||||
if (((parameterTypeList == null || parameterTypeList.length == 0) && argp.size() > 0)
|
||||
|| (argp.size() != parameterTypeList.length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int index = 0; index < argp.size(); index++) {
|
||||
if (!StringMatch.isMatch(argp.get(index), parameterTypeList[index])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<DubboMethodArg> args = dubboMethodMatch.getArgs();
|
||||
|
||||
if (args != null && args.size() > 0) {
|
||||
if (parameters == null || parameters.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (DubboMethodArg dubboMethodArg : args) {
|
||||
int index = dubboMethodArg.getIndex();
|
||||
if (index >= parameters.length) {
|
||||
throw new IndexOutOfBoundsException("DubboMethodArg index >= parameters.length");
|
||||
}
|
||||
if (!DubboMethodArg.isMatch(dubboMethodArg, parameters[index])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DubboMethodMatch{" +
|
||||
"name_match=" + name_match +
|
||||
", argc=" + argc +
|
||||
", args=" + args +
|
||||
", argp=" + argp +
|
||||
", headers=" + headers +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
public class ListBoolMatch {
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class ListDoubleMatch {
|
||||
private List<DoubleMatch> oneof;
|
||||
|
||||
public List<DoubleMatch> getOneof() {
|
||||
return oneof;
|
||||
}
|
||||
|
||||
public void setOneof(List<DoubleMatch> oneof) {
|
||||
this.oneof = oneof;
|
||||
}
|
||||
|
||||
public static boolean isMatch(ListDoubleMatch listDoubleMatch, Double input) {
|
||||
|
||||
for (DoubleMatch doubleMatch : listDoubleMatch.getOneof()) {
|
||||
if (DoubleMatch.isMatch(doubleMatch, input)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class ListStringMatch {
|
||||
private List<StringMatch> oneof;
|
||||
|
||||
public List<StringMatch> getOneof() {
|
||||
return oneof;
|
||||
}
|
||||
|
||||
public void setOneof(List<StringMatch> oneof) {
|
||||
this.oneof = oneof;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMatch(ListStringMatch listStringMatch, String input) {
|
||||
|
||||
for (StringMatch stringMatch : listStringMatch.getOneof()) {
|
||||
if (StringMatch.isMatch(stringMatch, input)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
public class StringMatch {
|
||||
private String exact;
|
||||
private String prefix;
|
||||
private String regex;
|
||||
private String noempty;
|
||||
private String empty;
|
||||
|
||||
|
||||
public String getExact() {
|
||||
return exact;
|
||||
}
|
||||
|
||||
public void setExact(String exact) {
|
||||
this.exact = exact;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getRegex() {
|
||||
return regex;
|
||||
}
|
||||
|
||||
public void setRegex(String regex) {
|
||||
this.regex = regex;
|
||||
}
|
||||
|
||||
public String getNoempty() {
|
||||
return noempty;
|
||||
}
|
||||
|
||||
public void setNoempty(String noempty) {
|
||||
this.noempty = noempty;
|
||||
}
|
||||
|
||||
public String getEmpty() {
|
||||
return empty;
|
||||
}
|
||||
|
||||
public void setEmpty(String empty) {
|
||||
this.empty = empty;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMatch(StringMatch stringMatch, String input) {
|
||||
if (stringMatch.getExact() != null && input != null) {
|
||||
if (input.equals(stringMatch.getExact())) {
|
||||
return true;
|
||||
}
|
||||
} else if (stringMatch.getPrefix() != null && input != null) {
|
||||
if (input.startsWith(stringMatch.getPrefix())) {
|
||||
return true;
|
||||
}
|
||||
} else if (stringMatch.getRegex() != null && input != null) {
|
||||
if (input.matches(stringMatch.getRegex())) {
|
||||
return true;
|
||||
}
|
||||
} else if (stringMatch.getEmpty() != null) {
|
||||
return input == null || "".equals(input);
|
||||
} else if (stringMatch.getNoempty() != null) {
|
||||
return input != null && input.length() > 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StringMatch{" +
|
||||
"exact='" + exact + '\'' +
|
||||
", prefix='" + prefix + '\'' +
|
||||
", regex='" + regex + '\'' +
|
||||
", noempty='" + noempty + '\'' +
|
||||
", empty='" + empty + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.util;
|
||||
|
||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class VsDestinationGroupRuleDispatcher {
|
||||
|
||||
private Set<VsDestinationGroupRuleListener> listenerSet = new ConcurrentHashSet<>();
|
||||
|
||||
public synchronized void post(VsDestinationGroup vsDestinationGroup) {
|
||||
for (VsDestinationGroupRuleListener vsDestinationGroupRuleListener : listenerSet) {
|
||||
try {
|
||||
vsDestinationGroupRuleListener.onRuleChange(vsDestinationGroup);
|
||||
} catch (Throwable throwable) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean register(VsDestinationGroupRuleListener listener) {
|
||||
if (listener == null) {
|
||||
return false;
|
||||
}
|
||||
return listenerSet.add(listener);
|
||||
}
|
||||
|
||||
public synchronized void unregister(VsDestinationGroupRuleListener listener) {
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
listenerSet.remove(listener);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.util;
|
||||
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
|
||||
|
||||
public interface VsDestinationGroupRuleListener {
|
||||
void onRuleChange(VsDestinationGroup vsDestinationGroup);
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleAddressListenerInterceptor
|
||||
|
|
@ -5,3 +5,4 @@ service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouterFactor
|
|||
app=org.apache.dubbo.rpc.cluster.router.condition.config.AppRouterFactory
|
||||
tag=org.apache.dubbo.rpc.cluster.router.tag.TagRouterFactory
|
||||
mock=org.apache.dubbo.rpc.cluster.router.mock.MockRouterFactory
|
||||
mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleRouterFactory
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.route;
|
||||
|
||||
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
|
||||
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
public class MeshAppRuleListenerTest {
|
||||
|
||||
@Test
|
||||
public void receiveConfigInfo() {
|
||||
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("qinliujie");
|
||||
|
||||
MeshRuleRouter meshRuleRouter = mock(MeshRuleRouter.class);
|
||||
meshAppRuleListener.register(meshRuleRouter);
|
||||
|
||||
meshAppRuleListener.receiveConfigInfo("apiVersion: service.dubbo.apache.org/v1alpha1\n" +
|
||||
"kind: DestinationRule\n" +
|
||||
"metadata: { name: demo-route }\n" +
|
||||
"spec:\n" +
|
||||
" host: demo\n" +
|
||||
" subsets:\n" +
|
||||
" - labels: { env-sign: xxx, tag1: hello }\n" +
|
||||
" name: isolation\n" +
|
||||
" - labels: { env-sign: yyy }\n" +
|
||||
" name: testing-trunk\n" +
|
||||
" - labels: { env-sign: zzz }\n" +
|
||||
" name: testing\n" +
|
||||
" trafficPolicy:\n" +
|
||||
" loadBalancer: { simple: ROUND_ROBIN }\n" +
|
||||
"\n" +
|
||||
"---\n" +
|
||||
"\n" +
|
||||
"apiVersion: service.dubbo.apache.org/v1alpha1\n" +
|
||||
"kind: VirtualService\n" +
|
||||
"metadata: {name: demo-route}\n" +
|
||||
"spec:\n" +
|
||||
" dubbo:\n" +
|
||||
" - routedetail:\n" +
|
||||
" - match:\n" +
|
||||
" - sourceLabels: {trafficLabel: xxx}\n" +
|
||||
" name: xxx-project\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: isolation}\n" +
|
||||
" - match:\n" +
|
||||
" - sourceLabels: {trafficLabel: testing-trunk}\n" +
|
||||
" name: testing-trunk\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: testing-trunk}\n" +
|
||||
" - name: testing\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: testing}\n" +
|
||||
" services:\n" +
|
||||
" - {regex: ccc}\n" +
|
||||
" hosts: [demo]\n");
|
||||
|
||||
|
||||
ArgumentCaptor<VsDestinationGroup> captor = ArgumentCaptor.forClass(VsDestinationGroup.class);
|
||||
verify(meshRuleRouter, times(1)).onRuleChange(captor.capture());
|
||||
|
||||
VsDestinationGroup vsDestinationGroup = captor.getValue();
|
||||
|
||||
assertTrue(vsDestinationGroup.getAppName().equals("qinliujie"));
|
||||
assertTrue(vsDestinationGroup.getDestinationRuleList().size() == 1);
|
||||
assertTrue(vsDestinationGroup.getVirtualServiceRuleList().size() == 1);
|
||||
|
||||
|
||||
meshAppRuleListener.receiveConfigInfo("");
|
||||
verify(meshRuleRouter, times(2)).onRuleChange(captor.capture());
|
||||
|
||||
VsDestinationGroup vsDestinationGroup1 = captor.getAllValues().get(captor.getAllValues().size() - 1);
|
||||
|
||||
assertTrue(vsDestinationGroup1.getAppName().equals("qinliujie"));
|
||||
assertTrue(vsDestinationGroup1.getDestinationRuleList().size() == 0);
|
||||
assertTrue(vsDestinationGroup1.getVirtualServiceRuleList().size() == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void register() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregister() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void process() {
|
||||
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener("qinliujie");
|
||||
|
||||
MeshRuleRouter meshRuleRouter = mock(MeshRuleRouter.class);
|
||||
meshAppRuleListener.register(meshRuleRouter);
|
||||
|
||||
ConfigChangedEvent configChangedEvent = new ConfigChangedEvent("qinliujie", "HSF", "apiVersion: service.dubbo.apache.org/v1alpha1\n" +
|
||||
"kind: DestinationRule\n" +
|
||||
"metadata: { name: demo-route }\n" +
|
||||
"spec:\n" +
|
||||
" host: demo\n" +
|
||||
" subsets:\n" +
|
||||
" - labels: { env-sign: xxx, tag1: hello }\n" +
|
||||
" name: isolation\n" +
|
||||
" - labels: { env-sign: yyy }\n" +
|
||||
" name: testing-trunk\n" +
|
||||
" - labels: { env-sign: zzz }\n" +
|
||||
" name: testing\n" +
|
||||
" trafficPolicy:\n" +
|
||||
" loadBalancer: { simple: ROUND_ROBIN }\n" +
|
||||
"\n" +
|
||||
"---\n" +
|
||||
"\n" +
|
||||
"apiVersion: service.dubbo.apache.org/v1alpha1\n" +
|
||||
"kind: VirtualService\n" +
|
||||
"metadata: {name: demo-route}\n" +
|
||||
"spec:\n" +
|
||||
" dubbo:\n" +
|
||||
" - routedetail:\n" +
|
||||
" - match:\n" +
|
||||
" - sourceLabels: {trafficLabel: xxx}\n" +
|
||||
" name: xxx-project\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: isolation}\n" +
|
||||
" - match:\n" +
|
||||
" - sourceLabels: {trafficLabel: testing-trunk}\n" +
|
||||
" name: testing-trunk\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: testing-trunk}\n" +
|
||||
" - name: testing\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: testing}\n" +
|
||||
" services:\n" +
|
||||
" - {regex: ccc}\n" +
|
||||
" hosts: [demo]\n", ConfigChangeType.MODIFIED);
|
||||
|
||||
|
||||
meshAppRuleListener.process(configChangedEvent);
|
||||
|
||||
ArgumentCaptor<VsDestinationGroup> captor = ArgumentCaptor.forClass(VsDestinationGroup.class);
|
||||
verify(meshRuleRouter, times(1)).onRuleChange(captor.capture());
|
||||
|
||||
VsDestinationGroup vsDestinationGroup = captor.getValue();
|
||||
|
||||
assertTrue(vsDestinationGroup.getAppName().equals("qinliujie"));
|
||||
assertTrue(vsDestinationGroup.getDestinationRuleList().size() == 1);
|
||||
assertTrue(vsDestinationGroup.getVirtualServiceRuleList().size() == 1);
|
||||
|
||||
|
||||
meshAppRuleListener.receiveConfigInfo("");
|
||||
verify(meshRuleRouter, times(2)).onRuleChange(captor.capture());
|
||||
|
||||
VsDestinationGroup vsDestinationGroup1 = captor.getAllValues().get(captor.getAllValues().size() - 1);
|
||||
|
||||
assertTrue(vsDestinationGroup1.getAppName().equals("qinliujie"));
|
||||
assertTrue(vsDestinationGroup1.getDestinationRuleList().size() == 0);
|
||||
assertTrue(vsDestinationGroup1.getVirtualServiceRuleList().size() == 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.route;
|
||||
|
||||
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.Matchers.anyLong;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
public class MeshRuleManagerTest {
|
||||
|
||||
@Test
|
||||
public void subscribeAppRule() {
|
||||
Optional<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
|
||||
try {
|
||||
DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
|
||||
|
||||
ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
|
||||
|
||||
MeshRuleManager.subscribeAppRule("test");
|
||||
|
||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||
Mockito.verify(dynamicConfiguration).getConfig(captor.capture(), anyString(), anyLong());
|
||||
|
||||
String result = captor.getValue();
|
||||
|
||||
assertEquals("test.MESHAPPRULE", result);
|
||||
} finally {
|
||||
ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void register() {
|
||||
Optional<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
|
||||
try {
|
||||
DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
|
||||
|
||||
ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
|
||||
|
||||
when(dynamicConfiguration.getConfig(anyString(), anyString(), anyLong())).thenReturn("apiVersion: service.dubbo.apache.org/v1alpha1\n" +
|
||||
"kind: VirtualService\n" +
|
||||
"metadata: {name: demo-route}\n" +
|
||||
"spec:\n" +
|
||||
" dubbo:\n" +
|
||||
" - routedetail:\n" +
|
||||
" - match:\n" +
|
||||
" - sourceLabels: {trafficLabel: xxx}\n" +
|
||||
" name: xxx-project\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: isolation}\n" +
|
||||
" - match:\n" +
|
||||
" - sourceLabels: {trafficLabel: testing-trunk}\n" +
|
||||
" name: testing-trunk\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: testing-trunk}\n" +
|
||||
" - name: testing\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: testing}\n" +
|
||||
" services:\n" +
|
||||
" - {regex: ccc}\n" +
|
||||
" hosts: [demo]\n");
|
||||
|
||||
MeshRuleManager.subscribeAppRule("test");
|
||||
|
||||
|
||||
MeshRuleRouter meshRuleRouter = mock(MeshRuleRouter.class);
|
||||
|
||||
MeshRuleManager.register("test", meshRuleRouter);
|
||||
|
||||
ArgumentCaptor<VsDestinationGroup> captor = ArgumentCaptor.forClass(VsDestinationGroup.class);
|
||||
|
||||
|
||||
Mockito.verify(meshRuleRouter).onRuleChange(captor.capture());
|
||||
|
||||
VsDestinationGroup result = captor.getValue();
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals("test", result.getAppName());
|
||||
assertEquals(1, result.getVirtualServiceRuleList().size());
|
||||
assertEquals(0, result.getDestinationRuleList().size());
|
||||
} finally {
|
||||
ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregister() {
|
||||
Optional<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
|
||||
try {
|
||||
DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
|
||||
|
||||
ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
|
||||
|
||||
when(dynamicConfiguration.getConfig(anyString(), anyString(), anyLong())).thenReturn("apiVersion: service.dubbo.apache.org/v1alpha1\n" +
|
||||
"kind: VirtualService\n" +
|
||||
"metadata: {name: demo-route}\n" +
|
||||
"spec:\n" +
|
||||
" dubbo:\n" +
|
||||
" - routedetail:\n" +
|
||||
" - match:\n" +
|
||||
" - sourceLabels: {trafficLabel: xxx}\n" +
|
||||
" name: xxx-project\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: isolation}\n" +
|
||||
" - match:\n" +
|
||||
" - sourceLabels: {trafficLabel: testing-trunk}\n" +
|
||||
" name: testing-trunk\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: testing-trunk}\n" +
|
||||
" - name: testing\n" +
|
||||
" route:\n" +
|
||||
" - destination: {host: demo, subset: testing}\n" +
|
||||
" services:\n" +
|
||||
" - {regex: ccc}\n" +
|
||||
" hosts: [demo]\n");
|
||||
|
||||
MeshRuleManager.subscribeAppRule("test");
|
||||
|
||||
|
||||
MeshRuleRouter meshRuleRouter = mock(MeshRuleRouter.class);
|
||||
|
||||
MeshRuleManager.register("test", meshRuleRouter);
|
||||
|
||||
MeshRuleManager.unregister(meshRuleRouter);
|
||||
|
||||
} finally {
|
||||
ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.route;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
public class MeshRuleRouterFactoryTest {
|
||||
|
||||
@Test
|
||||
public void getRouter() {
|
||||
MeshRuleRouterFactory ruleRouterFactory = new MeshRuleRouterFactory();
|
||||
URL url = mock(URL.class);
|
||||
when(url.getServiceKey()).thenReturn("demoService");
|
||||
ruleRouterFactory.getRouter(url);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance.SimpleLB;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
public class DestinationRuleTest {
|
||||
|
||||
@Test
|
||||
public void parserTest() {
|
||||
Yaml yaml = new Yaml();
|
||||
DestinationRule destinationRule = yaml.loadAs(this.getClass().getClassLoader().getResourceAsStream("DestinationRuleTest.yaml"), DestinationRule.class);
|
||||
|
||||
System.out.println(destinationRule);
|
||||
|
||||
|
||||
// apiVersion: service.dubbo.apache.org/v1alpha1
|
||||
// kind: DestinationRule
|
||||
// metadata: { name: demo-route }
|
||||
// spec:
|
||||
// host: demo
|
||||
// subsets:
|
||||
// - labels: { env-sign: xxx,tag1: hello }
|
||||
// name: isolation
|
||||
// - labels: { env-sign: yyy }
|
||||
// name: testing-trunk
|
||||
// - labels: { env-sign: zzz }
|
||||
// name: testing
|
||||
|
||||
|
||||
assertEquals("service.dubbo.apache.org/v1alpha1", destinationRule.getApiVersion());
|
||||
assertEquals("DestinationRule", destinationRule.getKind());
|
||||
assertEquals("demo-route", destinationRule.getMetadata().get("name"));
|
||||
assertEquals("demo", destinationRule.getSpec().getHost());
|
||||
assertEquals(3, destinationRule.getSpec().getSubsets().size());
|
||||
|
||||
assertEquals("isolation", destinationRule.getSpec().getSubsets().get(0).getName());
|
||||
assertEquals(2, destinationRule.getSpec().getSubsets().get(0).getLabels().size());
|
||||
assertEquals("xxx", destinationRule.getSpec().getSubsets().get(0).getLabels().get("env-sign"));
|
||||
assertEquals("hello", destinationRule.getSpec().getSubsets().get(0).getLabels().get("tag1"));
|
||||
|
||||
|
||||
assertEquals("testing-trunk", destinationRule.getSpec().getSubsets().get(1).getName());
|
||||
assertEquals(1, destinationRule.getSpec().getSubsets().get(1).getLabels().size());
|
||||
assertEquals("yyy", destinationRule.getSpec().getSubsets().get(1).getLabels().get("env-sign"));
|
||||
|
||||
|
||||
assertEquals("testing", destinationRule.getSpec().getSubsets().get(2).getName());
|
||||
assertEquals(1, destinationRule.getSpec().getSubsets().get(2).getLabels().size());
|
||||
assertEquals("zzz", destinationRule.getSpec().getSubsets().get(2).getLabels().get("env-sign"));
|
||||
|
||||
assertEquals(SimpleLB.ROUND_ROBIN, destinationRule.getSpec().getTrafficPolicy().getLoadBalancer().getSimple());
|
||||
assertEquals(null, destinationRule.getSpec().getTrafficPolicy().getLoadBalancer().getConsistentHash());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void parserMultiRuleTest() {
|
||||
Yaml yaml = new Yaml();
|
||||
Yaml yaml2 = new Yaml();
|
||||
Iterable objectIterable = yaml.loadAll(this.getClass().getClassLoader().getResourceAsStream("DestinationRuleTest2.yaml"));
|
||||
for (Object result : objectIterable) {
|
||||
|
||||
Map resultMap = (Map) result;
|
||||
if (resultMap.get("kind").equals("DestinationRule")) {
|
||||
DestinationRule destinationRule = yaml2.loadAs(yaml2.dump(result), DestinationRule.class);
|
||||
System.out.println(destinationRule);
|
||||
assertNotNull(destinationRule);
|
||||
} else if (resultMap.get("kind").equals("VirtualService")) {
|
||||
VirtualServiceRule virtualServiceRule = yaml2.loadAs(yaml2.dump(result), VirtualServiceRule.class);
|
||||
System.out.println(virtualServiceRule);
|
||||
assertNotNull(virtualServiceRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServiceRule;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
public class VirtualServiceRuleTest {
|
||||
|
||||
@Test
|
||||
public void parserTest() {
|
||||
Yaml yaml = new Yaml();
|
||||
VirtualServiceRule virtualServiceRule = yaml.loadAs(this.getClass().getClassLoader().getResourceAsStream("VirtualServiceTest.yaml"), VirtualServiceRule.class);
|
||||
|
||||
System.out.println(virtualServiceRule);
|
||||
assertNotNull(virtualServiceRule);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DubboAttachmentMatch;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.DubboMethodMatch;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
public class DubboMatchRequestTest {
|
||||
|
||||
@Test
|
||||
public void isMatch() {
|
||||
DubboMatchRequest dubboMatchRequest = new DubboMatchRequest();
|
||||
|
||||
// methodMatch
|
||||
{
|
||||
DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
|
||||
StringMatch nameStringMatch = new StringMatch();
|
||||
nameStringMatch.setExact("sayHello");
|
||||
dubboMethodMatch.setName_match(nameStringMatch);
|
||||
|
||||
dubboMatchRequest.setMethod(dubboMethodMatch);
|
||||
}
|
||||
assertTrue(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, new HashMap(), new HashMap(), new HashMap(), new HashMap()));
|
||||
assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHi", new String[]{}, new Object[]{}, new HashMap(), new HashMap(), new HashMap(), new HashMap()));
|
||||
// sourceLabels
|
||||
{
|
||||
Map<String, String> sourceLabels = new HashMap<>();
|
||||
sourceLabels.put("key1", "value1");
|
||||
sourceLabels.put("key2", "value2");
|
||||
|
||||
dubboMatchRequest.setSourceLabels(sourceLabels);
|
||||
}
|
||||
|
||||
Map<String, String> inputSourceLablesMap = new HashMap<>();
|
||||
inputSourceLablesMap.put("key1", "value1");
|
||||
inputSourceLablesMap.put("key2", "value2");
|
||||
inputSourceLablesMap.put("key3", "value3");
|
||||
|
||||
Map<String, String> inputSourceLablesMap2 = new HashMap<>();
|
||||
inputSourceLablesMap2.put("key1", "other");
|
||||
inputSourceLablesMap2.put("key2", "value2");
|
||||
inputSourceLablesMap2.put("key3", "value3");
|
||||
|
||||
assertTrue(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, new HashMap(), new HashMap(), new HashMap()));
|
||||
assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap2, new HashMap(), new HashMap(), new HashMap()));
|
||||
|
||||
|
||||
// eagleeyeContext
|
||||
{
|
||||
DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
|
||||
|
||||
{
|
||||
Map<String, StringMatch> eagleeyecontextMatchMap = new HashMap<>();
|
||||
StringMatch nameMatch = new StringMatch();
|
||||
nameMatch.setExact("qinliujie");
|
||||
eagleeyecontextMatchMap.put("name", nameMatch);
|
||||
dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap);
|
||||
}
|
||||
|
||||
dubboMatchRequest.setAttachments(dubboAttachmentMatch);
|
||||
}
|
||||
|
||||
Map<String, String> invokeEagleEyeContextMap = new HashMap<>();
|
||||
invokeEagleEyeContextMap.put("name", "qinliujie");
|
||||
invokeEagleEyeContextMap.put("machineGroup", "test_host");
|
||||
invokeEagleEyeContextMap.put("other", "other");
|
||||
|
||||
assertTrue(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap, new HashMap(), new HashMap()));
|
||||
|
||||
|
||||
Map<String, String> invokeEagleEyeContextMap2 = new HashMap<>();
|
||||
invokeEagleEyeContextMap2.put("name", "jack");
|
||||
invokeEagleEyeContextMap2.put("machineGroup", "test_host");
|
||||
invokeEagleEyeContextMap2.put("other", "other");
|
||||
|
||||
assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap2, new HashMap(), new HashMap()));
|
||||
|
||||
|
||||
//dubbo context
|
||||
|
||||
{
|
||||
DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
|
||||
|
||||
{
|
||||
Map<String, StringMatch> eagleeyecontextMatchMap = new HashMap<>();
|
||||
StringMatch nameMatch = new StringMatch();
|
||||
nameMatch.setExact("qinliujie");
|
||||
eagleeyecontextMatchMap.put("name", nameMatch);
|
||||
dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
Map<String, StringMatch> dubboContextMatchMap = new HashMap<>();
|
||||
StringMatch dpathMatch = new StringMatch();
|
||||
dpathMatch.setExact("PRE");
|
||||
dubboContextMatchMap.put("dpath", dpathMatch);
|
||||
dubboAttachmentMatch.setDubbocontext(dubboContextMatchMap);
|
||||
}
|
||||
|
||||
dubboMatchRequest.setAttachments(dubboAttachmentMatch);
|
||||
}
|
||||
|
||||
|
||||
Map<String, String> invokeDubboContextMap = new HashMap<>();
|
||||
invokeDubboContextMap.put("dpath", "PRE");
|
||||
|
||||
assertTrue(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap, invokeDubboContextMap, new HashMap()));
|
||||
|
||||
|
||||
Map<String, String> invokeDubboContextMap2 = new HashMap<>();
|
||||
invokeDubboContextMap.put("dpath", "other");
|
||||
|
||||
assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap, invokeDubboContextMap2, new HashMap()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class BoolMatchTest {
|
||||
|
||||
@Test
|
||||
public void isMatch() {
|
||||
BoolMatch boolMatch = new BoolMatch();
|
||||
boolMatch.setExact(true);
|
||||
|
||||
|
||||
assertTrue(BoolMatch.isMatch(boolMatch,true));
|
||||
assertFalse(BoolMatch.isMatch(boolMatch,false));
|
||||
|
||||
boolMatch.setExact(false);
|
||||
assertFalse(BoolMatch.isMatch(boolMatch,true));
|
||||
assertTrue(BoolMatch.isMatch(boolMatch,false));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class DoubleMatchTest {
|
||||
|
||||
@Test
|
||||
public void exactMatch() {
|
||||
DoubleMatch doubleMatch = new DoubleMatch();
|
||||
doubleMatch.setExact(10.0);
|
||||
|
||||
assertTrue(DoubleMatch.isMatch(doubleMatch, 10.0));
|
||||
assertFalse(DoubleMatch.isMatch(doubleMatch, 9.0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rangeStartMatch() {
|
||||
DoubleMatch doubleMatch = new DoubleMatch();
|
||||
|
||||
DoubleRangeMatch doubleRangeMatch = new DoubleRangeMatch();
|
||||
doubleRangeMatch.setStart(10.0);
|
||||
|
||||
doubleMatch.setRange(doubleRangeMatch);
|
||||
|
||||
assertTrue(DoubleMatch.isMatch(doubleMatch, 10.0));
|
||||
assertFalse(DoubleMatch.isMatch(doubleMatch, 9.0));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void rangeEndMatch() {
|
||||
DoubleMatch doubleMatch = new DoubleMatch();
|
||||
|
||||
DoubleRangeMatch doubleRangeMatch = new DoubleRangeMatch();
|
||||
doubleRangeMatch.setEnd(10.0);
|
||||
|
||||
doubleMatch.setRange(doubleRangeMatch);
|
||||
|
||||
assertFalse(DoubleMatch.isMatch(doubleMatch, 10.0));
|
||||
assertTrue(DoubleMatch.isMatch(doubleMatch, 9.0));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void rangeStartEndMatch() {
|
||||
DoubleMatch doubleMatch = new DoubleMatch();
|
||||
|
||||
DoubleRangeMatch doubleRangeMatch = new DoubleRangeMatch();
|
||||
doubleRangeMatch.setStart(5.0);
|
||||
doubleRangeMatch.setEnd(10.0);
|
||||
|
||||
doubleMatch.setRange(doubleRangeMatch);
|
||||
|
||||
assertTrue(DoubleMatch.isMatch(doubleMatch, 5.0));
|
||||
assertFalse(DoubleMatch.isMatch(doubleMatch, 10.0));
|
||||
|
||||
assertFalse(DoubleMatch.isMatch(doubleMatch, 4.9));
|
||||
assertFalse(DoubleMatch.isMatch(doubleMatch, 10.1));
|
||||
|
||||
assertTrue(DoubleMatch.isMatch(doubleMatch, 6.0));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modMatch() {
|
||||
DoubleMatch doubleMatch = new DoubleMatch();
|
||||
|
||||
doubleMatch.setMod(2.0);
|
||||
doubleMatch.setExact(3.0);
|
||||
|
||||
assertFalse(DoubleMatch.isMatch(doubleMatch, 3.0));
|
||||
|
||||
doubleMatch.setExact(1.0);
|
||||
|
||||
assertTrue(DoubleMatch.isMatch(doubleMatch, 1.0));
|
||||
assertFalse(DoubleMatch.isMatch(doubleMatch, 2.0));
|
||||
assertTrue(DoubleMatch.isMatch(doubleMatch, 3.0));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
public class DubboAttachmentMatchTest {
|
||||
|
||||
@Test
|
||||
public void dubboContextMatch() {
|
||||
DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
|
||||
|
||||
Map<String, StringMatch> dubbocontextMatchMap = new HashMap<>();
|
||||
|
||||
StringMatch nameMatch = new StringMatch();
|
||||
nameMatch.setExact("qinliujie");
|
||||
dubbocontextMatchMap.put("name", nameMatch);
|
||||
|
||||
|
||||
StringMatch machineGroupMatch = new StringMatch();
|
||||
machineGroupMatch.setExact("test_host");
|
||||
dubbocontextMatchMap.put("machineGroup", machineGroupMatch);
|
||||
|
||||
dubboAttachmentMatch.setDubbocontext(dubbocontextMatchMap);
|
||||
|
||||
Map<String, String> invokeDubboContextMap = new HashMap<>();
|
||||
invokeDubboContextMap.put("name", "qinliujie");
|
||||
invokeDubboContextMap.put("machineGroup", "test_host");
|
||||
invokeDubboContextMap.put("other", "other");
|
||||
|
||||
assertTrue(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, new HashMap<>(), invokeDubboContextMap));
|
||||
|
||||
|
||||
Map<String, String> invokeDubboContextMap2 = new HashMap<>();
|
||||
invokeDubboContextMap2.put("name", "jack");
|
||||
invokeDubboContextMap2.put("machineGroup", "test_host");
|
||||
invokeDubboContextMap2.put("other", "other");
|
||||
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, new HashMap<>(), invokeDubboContextMap2));
|
||||
|
||||
|
||||
Map<String, String> invokeDubboContextMap3 = new HashMap<>();
|
||||
invokeDubboContextMap3.put("name", "qinliujie");
|
||||
invokeDubboContextMap3.put("machineGroup", "my_host");
|
||||
invokeDubboContextMap3.put("other", "other");
|
||||
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, new HashMap<>(), invokeDubboContextMap3));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void eagleEyeContextMatch() {
|
||||
DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
|
||||
|
||||
Map<String, StringMatch> eagleeyecontextMatchMap = new HashMap<>();
|
||||
|
||||
StringMatch nameMatch = new StringMatch();
|
||||
nameMatch.setExact("qinliujie");
|
||||
eagleeyecontextMatchMap.put("name", nameMatch);
|
||||
|
||||
|
||||
StringMatch machineGroupMatch = new StringMatch();
|
||||
machineGroupMatch.setExact("test_host");
|
||||
eagleeyecontextMatchMap.put("machineGroup", machineGroupMatch);
|
||||
|
||||
dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap);
|
||||
|
||||
Map<String, String> invokeEagleEyeContextMap = new HashMap<>();
|
||||
invokeEagleEyeContextMap.put("name", "qinliujie");
|
||||
invokeEagleEyeContextMap.put("machineGroup", "test_host");
|
||||
invokeEagleEyeContextMap.put("other", "other");
|
||||
|
||||
assertTrue(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, new HashMap<>()));
|
||||
|
||||
|
||||
Map<String, String> invokeEagleEyeContextMap2 = new HashMap<>();
|
||||
invokeEagleEyeContextMap2.put("name", "jack");
|
||||
invokeEagleEyeContextMap2.put("machineGroup", "test_host");
|
||||
invokeEagleEyeContextMap2.put("other", "other");
|
||||
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, new HashMap<>()));
|
||||
|
||||
|
||||
Map<String, String> invokeEagleEyeContextMap3 = new HashMap<>();
|
||||
invokeEagleEyeContextMap3.put("name", "qinliujie");
|
||||
invokeEagleEyeContextMap3.put("machineGroup", "my_host");
|
||||
invokeEagleEyeContextMap3.put("other", "other");
|
||||
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap3, new HashMap<>()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void contextMatch() {
|
||||
DubboAttachmentMatch dubboAttachmentMatch = new DubboAttachmentMatch();
|
||||
|
||||
{
|
||||
Map<String, StringMatch> eagleeyecontextMatchMap = new HashMap<>();
|
||||
StringMatch nameMatch = new StringMatch();
|
||||
nameMatch.setExact("qinliujie");
|
||||
eagleeyecontextMatchMap.put("name", nameMatch);
|
||||
dubboAttachmentMatch.setEagleeyecontext(eagleeyecontextMatchMap);
|
||||
}
|
||||
|
||||
|
||||
Map<String, String> invokeEagleEyeContextMap = new HashMap<>();
|
||||
invokeEagleEyeContextMap.put("name", "qinliujie");
|
||||
invokeEagleEyeContextMap.put("machineGroup", "test_host");
|
||||
invokeEagleEyeContextMap.put("other", "other");
|
||||
|
||||
//-------
|
||||
|
||||
{
|
||||
Map<String, StringMatch> dubboContextMatchMap = new HashMap<>();
|
||||
StringMatch dpathMatch = new StringMatch();
|
||||
dpathMatch.setExact("PRE");
|
||||
dubboContextMatchMap.put("dpath", dpathMatch);
|
||||
dubboAttachmentMatch.setDubbocontext(dubboContextMatchMap);
|
||||
}
|
||||
|
||||
Map<String, String> invokeDubboContextMap = new HashMap<>();
|
||||
invokeDubboContextMap.put("dpath", "PRE");
|
||||
|
||||
|
||||
assertTrue(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, invokeDubboContextMap));
|
||||
|
||||
|
||||
Map<String, String> invokeEagleEyeContextMap1 = new HashMap<>();
|
||||
invokeEagleEyeContextMap1.put("name", "jack");
|
||||
invokeEagleEyeContextMap1.put("machineGroup", "test_host");
|
||||
invokeEagleEyeContextMap1.put("other", "other");
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap1, invokeDubboContextMap));
|
||||
|
||||
|
||||
Map<String, String> invokeDubboContextMap1 = new HashMap<>();
|
||||
invokeDubboContextMap1.put("dpath", "PRE-2");
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, invokeDubboContextMap1));
|
||||
|
||||
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap1, invokeDubboContextMap1));
|
||||
|
||||
|
||||
Map<String, String> invokeEagleEyeContextMap2 = new HashMap<>();
|
||||
invokeEagleEyeContextMap2.put("machineGroup", "test_host");
|
||||
invokeEagleEyeContextMap2.put("other", "other");
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, invokeDubboContextMap));
|
||||
|
||||
Map<String, String> invokeDubboContextMap2 = new HashMap<>();
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap, invokeDubboContextMap2));
|
||||
|
||||
|
||||
assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, invokeDubboContextMap2));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class DubboMethodMatchTest {
|
||||
|
||||
@Test
|
||||
public void nameMatch() {
|
||||
DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
|
||||
|
||||
StringMatch nameStringMatch = new StringMatch();
|
||||
nameStringMatch.setExact("sayHello");
|
||||
|
||||
dubboMethodMatch.setName_match(nameStringMatch);
|
||||
|
||||
assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, new Object[]{}));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void argcMatch() {
|
||||
DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
|
||||
dubboMethodMatch.setArgc(1);
|
||||
|
||||
assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, new Object[]{}));
|
||||
assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, null));
|
||||
|
||||
assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, new Object[]{"1"}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void argpMatch() {
|
||||
DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
|
||||
|
||||
List<StringMatch> argpMatch = new ArrayList<>();
|
||||
|
||||
StringMatch first = new StringMatch();
|
||||
first.setExact("java.lang.Long");
|
||||
|
||||
StringMatch second = new StringMatch();
|
||||
second.setRegex(".*");
|
||||
|
||||
argpMatch.add(first);
|
||||
argpMatch.add(second);
|
||||
|
||||
dubboMethodMatch.setArgp(argpMatch);
|
||||
|
||||
|
||||
assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{"java.lang.Long", "java.lang.String"}, new Object[]{}));
|
||||
assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{"java.lang.Long", "java.lang.String", "java.lang.String"}, new Object[]{}));
|
||||
assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", new String[]{}, new Object[]{}));
|
||||
assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "sayHello", null, new Object[]{}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parametersMatch() {
|
||||
|
||||
|
||||
DubboMethodMatch dubboMethodMatch = new DubboMethodMatch();
|
||||
|
||||
List<DubboMethodArg> parametersMatch = new ArrayList<>();
|
||||
|
||||
//----- index 0
|
||||
{
|
||||
DubboMethodArg dubboMethodArg0 = new DubboMethodArg();
|
||||
dubboMethodArg0.setIndex(0);
|
||||
|
||||
ListDoubleMatch listDoubleMatch = new ListDoubleMatch();
|
||||
List<DoubleMatch> oneof = new ArrayList<>();
|
||||
|
||||
DoubleMatch doubleMatch1 = new DoubleMatch();
|
||||
doubleMatch1.setExact(10.0);
|
||||
|
||||
oneof.add(doubleMatch1);
|
||||
|
||||
listDoubleMatch.setOneof(oneof);
|
||||
|
||||
dubboMethodArg0.setNum_value(listDoubleMatch);
|
||||
|
||||
parametersMatch.add(dubboMethodArg0);
|
||||
}
|
||||
|
||||
//-----index 1
|
||||
|
||||
{
|
||||
|
||||
DubboMethodArg dubboMethodArg1 = new DubboMethodArg();
|
||||
dubboMethodArg1.setIndex(1);
|
||||
|
||||
ListStringMatch listStringMatch = new ListStringMatch();
|
||||
|
||||
List<StringMatch> oneof = new ArrayList<>();
|
||||
|
||||
StringMatch stringMatch1 = new StringMatch();
|
||||
stringMatch1.setExact("sayHello");
|
||||
|
||||
oneof.add(stringMatch1);
|
||||
|
||||
listStringMatch.setOneof(oneof);
|
||||
|
||||
dubboMethodArg1.setStr_value(listStringMatch);
|
||||
|
||||
parametersMatch.add(dubboMethodArg1);
|
||||
}
|
||||
|
||||
dubboMethodMatch.setArgs(parametersMatch);
|
||||
|
||||
assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String"}, new Object[]{10, "sayHello"}));
|
||||
assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String"}, new Object[]{10, "sayHi"}));
|
||||
|
||||
|
||||
//-----index 2
|
||||
|
||||
{
|
||||
|
||||
DubboMethodArg dubboMethodArg2 = new DubboMethodArg();
|
||||
dubboMethodArg2.setIndex(2);
|
||||
|
||||
BoolMatch boolMatch = new BoolMatch();
|
||||
boolMatch.setExact(true);
|
||||
|
||||
|
||||
dubboMethodArg2.setBool_value(boolMatch);
|
||||
|
||||
parametersMatch.add(dubboMethodArg2);
|
||||
}
|
||||
|
||||
|
||||
assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String", "boolean"}, new Object[]{10, "sayHello", true}));
|
||||
assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String", "boolean"}, new Object[]{10, "sayHello", false}));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
public class ListDoubleMatchTest {
|
||||
|
||||
@Test
|
||||
public void isMatch() {
|
||||
ListDoubleMatch listDoubleMatch = new ListDoubleMatch();
|
||||
List<DoubleMatch> oneof = new ArrayList<>();
|
||||
|
||||
DoubleMatch doubleMatch1 = new DoubleMatch();
|
||||
doubleMatch1.setExact(10.0);
|
||||
|
||||
DoubleMatch doubleMatch2 = new DoubleMatch();
|
||||
doubleMatch2.setExact(11.0);
|
||||
|
||||
oneof.add(doubleMatch1);
|
||||
oneof.add(doubleMatch2);
|
||||
|
||||
listDoubleMatch.setOneof(oneof);
|
||||
|
||||
assertTrue(ListDoubleMatch.isMatch(listDoubleMatch, 10.0));
|
||||
assertTrue(ListDoubleMatch.isMatch(listDoubleMatch, 11.0));
|
||||
assertFalse(ListDoubleMatch.isMatch(listDoubleMatch, 12.0));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ListStringMatchTest {
|
||||
|
||||
@Test
|
||||
public void isMatch() {
|
||||
ListStringMatch listStringMatch = new ListStringMatch();
|
||||
|
||||
List<StringMatch> oneof = new ArrayList<>();
|
||||
|
||||
StringMatch stringMatch1 = new StringMatch();
|
||||
stringMatch1.setExact("1");
|
||||
|
||||
StringMatch stringMatch2 = new StringMatch();
|
||||
stringMatch2.setExact("2");
|
||||
|
||||
oneof.add(stringMatch1);
|
||||
oneof.add(stringMatch2);
|
||||
|
||||
|
||||
listStringMatch.setOneof(oneof);
|
||||
|
||||
assertTrue(ListStringMatch.isMatch(listStringMatch, "1"));
|
||||
assertTrue(ListStringMatch.isMatch(listStringMatch, "2"));
|
||||
assertFalse(ListStringMatch.isMatch(listStringMatch, "3"));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class StringMatchTest {
|
||||
|
||||
@Test
|
||||
public void exactMatch() {
|
||||
StringMatch stringMatch = new StringMatch();
|
||||
stringMatch.setExact("qinliujie");
|
||||
|
||||
assertTrue(StringMatch.isMatch(stringMatch, "qinliujie"));
|
||||
assertFalse(StringMatch.isMatch(stringMatch, "other"));
|
||||
assertFalse(StringMatch.isMatch(stringMatch, null));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void prefixMatch() {
|
||||
StringMatch stringMatch = new StringMatch();
|
||||
stringMatch.setPrefix("org.apache.dubbo.rpc.cluster.router.mesh");
|
||||
|
||||
assertTrue(StringMatch.isMatch(stringMatch, "org.apache.dubbo.rpc.cluster.router.mesh.test"));
|
||||
assertFalse(StringMatch.isMatch(stringMatch, "com.alibaba.hsf"));
|
||||
assertFalse(StringMatch.isMatch(stringMatch, null));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void regxMatch() {
|
||||
StringMatch stringMatch = new StringMatch();
|
||||
stringMatch.setRegex("org.apache.dubbo.rpc.cluster.router.mesh.*");
|
||||
|
||||
assertTrue(StringMatch.isMatch(stringMatch, "org.apache.dubbo.rpc.cluster.router.mesh"));
|
||||
assertTrue(StringMatch.isMatch(stringMatch, "org.apache.dubbo.rpc.cluster.router.mesh.test"));
|
||||
assertFalse(StringMatch.isMatch(stringMatch, "com.alibaba.hsf"));
|
||||
assertFalse(StringMatch.isMatch(stringMatch, "com.taobao"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void emptyMatch() {
|
||||
StringMatch stringMatch = new StringMatch();
|
||||
stringMatch.setEmpty("empty");
|
||||
|
||||
assertFalse(StringMatch.isMatch(stringMatch, "com.alibaba.hsf"));
|
||||
assertTrue(StringMatch.isMatch(stringMatch, ""));
|
||||
assertTrue(StringMatch.isMatch(stringMatch, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noEmptyMatch() {
|
||||
StringMatch stringMatch = new StringMatch();
|
||||
stringMatch.setNoempty("noempty");
|
||||
|
||||
assertTrue(StringMatch.isMatch(stringMatch, "com.alibaba.hsf"));
|
||||
assertFalse(StringMatch.isMatch(stringMatch, ""));
|
||||
assertFalse(StringMatch.isMatch(stringMatch, null));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.mesh.util;
|
||||
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
||||
class VsDestinationGroupRuleDispatcherTest {
|
||||
|
||||
@Test
|
||||
public void post() {
|
||||
VsDestinationGroupRuleDispatcher vsDestinationGroupRuleDispatcher = new VsDestinationGroupRuleDispatcher();
|
||||
|
||||
VsDestinationGroupRuleListener vsDestinationGroupRuleListener = mock(VsDestinationGroupRuleListener.class);
|
||||
|
||||
vsDestinationGroupRuleDispatcher.register(vsDestinationGroupRuleListener);
|
||||
|
||||
vsDestinationGroupRuleDispatcher.post(new VsDestinationGroup());
|
||||
vsDestinationGroupRuleDispatcher.post(new VsDestinationGroup());
|
||||
|
||||
verify(vsDestinationGroupRuleListener, times(2)).onRuleChange(anyObject());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void register() {
|
||||
VsDestinationGroupRuleDispatcher vsDestinationGroupRuleDispatcher = new VsDestinationGroupRuleDispatcher();
|
||||
|
||||
VsDestinationGroupRuleListener vsDestinationGroupRuleListener = mock(VsDestinationGroupRuleListener.class);
|
||||
|
||||
assertFalse(vsDestinationGroupRuleDispatcher.register(null));
|
||||
assertTrue(vsDestinationGroupRuleDispatcher.register(vsDestinationGroupRuleListener));
|
||||
assertFalse(vsDestinationGroupRuleDispatcher.register(vsDestinationGroupRuleListener));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregister() {
|
||||
|
||||
VsDestinationGroupRuleDispatcher vsDestinationGroupRuleDispatcher = new VsDestinationGroupRuleDispatcher();
|
||||
|
||||
VsDestinationGroupRuleListener vsDestinationGroupRuleListener = mock(VsDestinationGroupRuleListener.class);
|
||||
vsDestinationGroupRuleDispatcher.register(vsDestinationGroupRuleListener);
|
||||
|
||||
vsDestinationGroupRuleDispatcher.post(new VsDestinationGroup());
|
||||
|
||||
vsDestinationGroupRuleDispatcher.unregister(vsDestinationGroupRuleListener);
|
||||
vsDestinationGroupRuleDispatcher.post(new VsDestinationGroup());
|
||||
|
||||
verify(vsDestinationGroupRuleListener, times(1)).onRuleChange(anyObject());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
#
|
||||
#
|
||||
|
||||
apiVersion: service.dubbo.apache.org/v1alpha1
|
||||
kind: DestinationRule
|
||||
metadata: { name: demo-route }
|
||||
spec:
|
||||
host: demo
|
||||
subsets:
|
||||
- labels: { env-sign: xxx, tag1: hello }
|
||||
name: isolation
|
||||
- labels: { env-sign: yyy }
|
||||
name: testing-trunk
|
||||
- labels: { env-sign: zzz }
|
||||
name: testing
|
||||
trafficPolicy:
|
||||
loadBalancer: { simple: ROUND_ROBIN }
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
#
|
||||
#
|
||||
|
||||
apiVersion: service.dubbo.apache.org/v1alpha1
|
||||
kind: DestinationRule
|
||||
metadata: { name: demo-route }
|
||||
spec:
|
||||
host: demo
|
||||
subsets:
|
||||
- labels: { env-sign: xxx, tag1: hello }
|
||||
name: isolation
|
||||
- labels: { env-sign: yyy }
|
||||
name: testing-trunk
|
||||
- labels: { env-sign: zzz }
|
||||
name: testing
|
||||
trafficPolicy:
|
||||
loadBalancer: { simple: ROUND_ROBIN }
|
||||
|
||||
---
|
||||
|
||||
apiVersion: service.dubbo.apache.org/v1alpha1
|
||||
kind: VirtualService
|
||||
metadata: {name: demo-route}
|
||||
spec:
|
||||
dubbo:
|
||||
- routedetail:
|
||||
- match:
|
||||
- sourceLabels: {trafficLabel: xxx}
|
||||
name: xxx-project
|
||||
route:
|
||||
- destination: {host: demo, subset: isolation}
|
||||
- match:
|
||||
- sourceLabels: {trafficLabel: testing-trunk}
|
||||
name: testing-trunk
|
||||
route:
|
||||
- destination: {host: demo, subset: testing-trunk}
|
||||
- name: testing
|
||||
route:
|
||||
- destination: {host: demo, subset: testing}
|
||||
services:
|
||||
- {regex: ccc}
|
||||
hosts: [demo]
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
#
|
||||
#
|
||||
|
||||
apiVersion: service.dubbo.apache.org/v1alpha1
|
||||
kind: VirtualService
|
||||
metadata: {name: demo-route}
|
||||
spec:
|
||||
dubbo:
|
||||
- routedetail:
|
||||
- match:
|
||||
- sourceLabels: {trafficLabel: xxx}
|
||||
name: xxx-project
|
||||
route:
|
||||
- destination: {host: demo, subset: isolation}
|
||||
- match:
|
||||
- sourceLabels: {trafficLabel: testing-trunk}
|
||||
name: testing-trunk
|
||||
route:
|
||||
- destination: {host: demo, subset: testing-trunk}
|
||||
- name: testing
|
||||
route:
|
||||
- destination: {host: demo, subset: testing}
|
||||
services:
|
||||
- {regex: ccc}
|
||||
hosts: [demo]
|
||||
Loading…
Reference in New Issue