develop-for-dubbo-3.x branch merge to develop branch (#808)
* [3.0]Add mesh rule route (#789)
* add mesh rule route
* add mesh rule check
* For #756 (#791)
* [ISSUE #760]Application discover support (#807)
* application discover support
* fix checkstyle
* fix ci
* remove useless pom import,modify Chinese comment
* fix UT bug
Co-authored-by: haoyann <1064645534@qq.com>
Co-authored-by: Aaron-boom <55744718+Aaron-boom@users.noreply.github.com>
diff --git a/dubbo-admin-server/pom.xml b/dubbo-admin-server/pom.xml
index d03d5ab..9973cd6 100644
--- a/dubbo-admin-server/pom.xml
+++ b/dubbo-admin-server/pom.xml
@@ -129,6 +129,11 @@
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
+ <groupId>org.apache.curator</groupId>
+ <artifactId>curator-x-discovery</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
@@ -173,11 +178,6 @@
</dependency>
<dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-serialization-kryo</artifactId>
- </dependency>
-
- <dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito-version}</version>
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/LoginAuthentication.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/LoginAuthentication.java
new file mode 100644
index 0000000..c9445e6
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/LoginAuthentication.java
@@ -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.
+ */
+
+package org.apache.dubbo.admin.authentication;
+
+import org.apache.dubbo.common.extension.SPI;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Logon permission authentication
+ *
+ */
+@SPI
+public interface LoginAuthentication {
+
+ boolean authentication(HttpServletRequest request, String userName, String password);
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
index f98a0d9..aa694b7 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
@@ -79,7 +79,8 @@
public static final String METRICS_PROTOCOL = "metrics.protocol";
public static final Set<String> CONFIGS = new HashSet<>();
public static final String COLON = ":";
-
+ public static final String MESH_RULE_SUFFIX = ".MESHAPPRULE";
+ public static final String DEFAULT_MAPPING_GROUP = "mapping";
static {
CONFIGS.add(WEIGHT);
CONFIGS.add(BALANCING);
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java
index e1dd54b..5ab5087 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java
@@ -19,10 +19,10 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.admin.model.domain.MethodMetadata;
-import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.definition.model.MethodDefinition;
-import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
-import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+import org.apache.dubbo.admin.model.domain.FullServiceDefinition;
+import org.apache.dubbo.admin.model.domain.MethodDefinition;
+import org.apache.dubbo.admin.model.domain.ServiceDefinition;
+import org.apache.dubbo.admin.model.domain.TypeDefinition;
import java.util.ArrayList;
import java.util.Collections;
@@ -180,10 +180,7 @@
keyType = StringUtils.strip(keyType);
Map<Object, Object> map = new HashMap<>();
- // 生成 key 默认值
Object key = generateType(sd, keyType);
-
- // 生成 value 默认值
String valueType = StringUtils.substringAfter(td.getType(), ",");
valueType = StringUtils.substringBefore(valueType, ">");
valueType = StringUtils.strip(valueType);
@@ -197,7 +194,7 @@
String type = StringUtils.substringAfter(td.getType(), "<");
type = StringUtils.substringBefore(type, ">");
if (StringUtils.isEmpty(type)) {
- // 如果 collection 类型未声明,则生成空 collection
+ // if type is null return empty collection
return new Object[] {};
}
return new Object[]{generateType(sd, type)};
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestV3Util.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestV3Util.java
new file mode 100644
index 0000000..63e294f
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestV3Util.java
@@ -0,0 +1,233 @@
+/*
+ * 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.admin.common.util;
+
+import org.apache.dubbo.admin.model.domain.MethodMetadata;
+import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ServiceTestV3Util {
+ private static Pattern COLLECTION_PATTERN = Pattern.compile("^java\\.util\\..*(Set|List|Queue|Collection|Deque)(<.*>)*$");
+ private static Pattern MAP_PATTERN = Pattern.compile("^java\\.util\\..*Map.*(<.*>)*$");
+
+ public static boolean sameMethod(MethodDefinition m, String methodSig) {
+ String name = m.getName();
+ String[] parameters = m.getParameterTypes();
+ StringBuilder sb = new StringBuilder();
+ sb.append(name).append("~");
+ for (String parameter : parameters) {
+ sb.append(parameter).append(";");
+ }
+ String sig = StringUtils.removeEnd(sb.toString(), ";");
+ return sig.equals(methodSig);
+ }
+
+ public static MethodMetadata generateMethodMeta(FullServiceDefinition serviceDefinition, MethodDefinition methodDefinition) {
+ MethodMetadata methodMetadata = new MethodMetadata();
+ String[] parameterTypes = methodDefinition.getParameterTypes();
+ String returnType = methodDefinition.getReturnType();
+ String signature = methodDefinition.getName() + "~" + String.join(";", parameterTypes);
+ methodMetadata.setSignature(signature);
+ methodMetadata.setReturnType(returnType);
+ List<Object> parameters = generateParameterTypes(parameterTypes, serviceDefinition);
+ methodMetadata.setParameterTypes(parameters);
+ return methodMetadata;
+ }
+
+ private static boolean isPrimitiveType(TypeDefinition td) {
+ String type = td.getType();
+ return isPrimitiveType(type);
+ }
+
+ private static boolean isPrimitiveType(String type) {
+ return type.equals("byte") || type.equals("java.lang.Byte") ||
+ type.equals("short") || type.equals("java.lang.Short") ||
+ type.equals("int") || type.equals("java.lang.Integer") ||
+ type.equals("long") || type.equals("java.lang.Long") ||
+ type.equals("float") || type.equals("java.lang.Float") ||
+ type.equals("double") || type.equals("java.lang.Double") ||
+ type.equals("boolean") || type.equals("java.lang.Boolean") ||
+ type.equals("void") || type.equals("java.lang.Void") ||
+ type.equals("java.lang.String") ||
+ type.equals("java.util.Date") ||
+ type.equals("java.lang.Object");
+ }
+
+ private static List<Object> generateParameterTypes(String[] parameterTypes, ServiceDefinition serviceDefinition) {
+ List<Object> parameters = new ArrayList<>();
+ for (String type : parameterTypes) {
+ Object result = generateType(serviceDefinition, type);
+ parameters.add(result);
+ }
+ return parameters;
+ }
+
+ private static TypeDefinition findTypeDefinition(ServiceDefinition serviceDefinition, String type) {
+ return serviceDefinition.getTypes().stream()
+ .filter(t -> t.getType().equals(type))
+ .findFirst().orElse(new TypeDefinition(type));
+ }
+
+ private static void generateComplexType(ServiceDefinition sd, TypeDefinition td, Map<String, Object> holder) {
+ td.getProperties().forEach((name, type) -> {
+ if (isPrimitiveType(type)) {
+ holder.put(name, generatePrimitiveType(type));
+ } else {
+ generateEnclosedType(holder, name, sd, type);
+ }
+ });
+ }
+
+ private static Object generateComplexType(ServiceDefinition sd, TypeDefinition td) {
+ Map<String, Object> holder = new HashMap<>();
+ generateComplexType(sd, td, holder);
+ return holder;
+ }
+
+ private static boolean isMap(TypeDefinition td) {
+ String type = StringUtils.substringBefore(td.getType(), "<");
+ Matcher matcher = MAP_PATTERN.matcher(type);
+ return matcher.matches();
+ }
+
+ private static boolean isCollection(TypeDefinition td) {
+ String type = StringUtils.substringBefore(td.getType(), "<");
+ Matcher matcher = COLLECTION_PATTERN.matcher(type);
+ return matcher.matches();
+ }
+
+ private static boolean isArray(TypeDefinition td) {
+ return StringUtils.endsWith(td.getType(), "[]");
+ }
+
+ private static Object generatePrimitiveType(TypeDefinition td) {
+ return generatePrimitiveType(td.getType());
+ }
+
+ private static Object generatePrimitiveType(String type) {
+ switch (type) {
+ case "byte":
+ case "java.lang.Byte":
+ case "short":
+ case "java.lang.Short":
+ case "int":
+ case "java.lang.Integer":
+ case "long":
+ case "java.lang.Long":
+ return 0;
+ case "float":
+ case "java.lang.Float":
+ case "double":
+ case "java.lang.Double":
+ return 0.0;
+ case "boolean":
+ case "java.lang.Boolean":
+ return true;
+ case "void":
+ case "java.lang.Void":
+ return null;
+ case "java.lang.String":
+ return "";
+ case "java.lang.Object":
+ return Collections.emptyMap();
+ case "java.util.Date":
+ return System.currentTimeMillis();
+ default:
+ return Collections.emptyMap();
+ }
+ }
+
+ private static Object generateType(ServiceDefinition sd, String type) {
+ TypeDefinition td = findTypeDefinition(sd, type);
+ return generateType(sd, td);
+ }
+
+ private static Object generateType(ServiceDefinition sd, TypeDefinition td) {
+ if (isPrimitiveType(td)) {
+ return generatePrimitiveType(td);
+ } else if (isMap(td)) {
+ return generateMapType(sd, td);
+ } else if (isArray(td)) {
+ return generateArrayType(sd, td);
+ } else if (isCollection(td)) {
+ return generateCollectionType(sd, td);
+ } else {
+ return generateComplexType(sd, td);
+ }
+ }
+
+ private static Object generateMapType(ServiceDefinition sd, TypeDefinition td) {
+ String keyType = StringUtils.substringAfter(td.getType(), "<");
+ keyType = StringUtils.substringBefore(keyType, ",");
+ keyType = StringUtils.strip(keyType);
+
+ Map<Object, Object> map = new HashMap<>();
+ Object key = generateType(sd, keyType);
+ String valueType = StringUtils.substringAfter(td.getType(), ",");
+ valueType = StringUtils.substringBefore(valueType, ">");
+ valueType = StringUtils.strip(valueType);
+ valueType = StringUtils.isNotEmpty(valueType) ? valueType : "java.lang.Object";
+ Object value = generateType(sd, valueType);
+ map.put(key, value);
+ return map;
+ }
+
+ private static Object generateCollectionType(ServiceDefinition sd, TypeDefinition td) {
+ String type = StringUtils.substringAfter(td.getType(), "<");
+ type = StringUtils.substringBefore(type, ">");
+ if (StringUtils.isEmpty(type)) {
+ // if type is null return empty collection
+ return new Object[]{};
+ }
+ return new Object[]{generateType(sd, type)};
+
+ }
+
+ private static Object generateArrayType(ServiceDefinition sd, TypeDefinition td) {
+ String type = StringUtils.substringBeforeLast(td.getType(), "[]");
+ return new Object[]{generateType(sd, type)};
+ }
+
+ private static void generateEnclosedType(Map<String, Object> holder, String key, ServiceDefinition sd, String type) {
+ if (isPrimitiveType(type)) {
+ holder.put(key, generateType(sd, type));
+ } else {
+ TypeDefinition td = findTypeDefinition(sd, type);
+ if (td.getProperties() == null || td.getProperties().size() == 0) {
+ holder.put(key, generateType(sd, td));
+ } else {
+ Map<String, Object> enclosedMap = new HashMap<>();
+ holder.put(key, enclosedMap);
+ generateComplexType(sd, td, enclosedMap);
+ }
+
+ }
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
index b548d91..88e9e73 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
@@ -18,6 +18,8 @@
import org.apache.dubbo.admin.model.domain.Consumer;
import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.admin.model.domain.RegistrySource;
+import org.apache.dubbo.common.BaseServiceMetadata;
import org.apache.dubbo.common.URL;
import java.util.ArrayList;
@@ -48,7 +50,10 @@
Provider p = new Provider();
p.setHash(id);
- p.setService(url.getServiceKey());
+ String group = url.getUrlParam().getParameter(Constants.GROUP_KEY);
+ String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
+ String service = BaseServiceMetadata.buildServiceKey(url.getServiceInterface(), group, version);
+ p.setService(service);
p.setAddress(url.getAddress());
p.setApplication(url.getParameter(Constants.APPLICATION_KEY));
p.setUrl(url.toIdentityString());
@@ -58,6 +63,7 @@
p.setEnabled(url.getParameter(Constants.ENABLED_KEY, true));
p.setWeight(url.getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT));
p.setUsername(url.getParameter("owner"));
+ p.setRegistrySource(RegistrySource.INTERFACE);
return p;
}
@@ -83,7 +89,10 @@
Consumer c = new Consumer();
c.setHash(id);
- c.setService(url.getServiceKey());
+ String group = url.getUrlParam().getParameter(Constants.GROUP_KEY);
+ String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
+ String service = BaseServiceMetadata.buildServiceKey(url.getServiceInterface(), group, version);
+ c.setService(service);
c.setAddress(url.getHost());
c.setApplication(url.getParameter(Constants.APPLICATION_KEY));
c.setParameters(url.toParameterString());
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
index 024097d..81ec3b3 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
@@ -17,7 +17,7 @@
package org.apache.dubbo.admin.common.util;
-import org.apache.dubbo.common.utils.PojoUtils;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.error.YAMLException;
@@ -30,6 +30,8 @@
public class YamlParser {
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
public static String dumpObject(Object object) {
return new Yaml(new SafeConstructor(), new CustomRepresenter()).dumpAsMap(object);
}
@@ -37,12 +39,16 @@
public static <T> T loadObject(String content, Class<T> type) {
Map<String, Object> map = new Yaml(new SafeConstructor(), new CustomRepresenter()).load(content);
try {
- return (T) PojoUtils.mapToPojo(map, type);
+ return OBJECT_MAPPER.convertValue(map, type);
} catch (Exception e) {
throw new YAMLException(e);
}
}
+ public static Iterable<Object> loadAll(String content) {
+ return new Yaml(new SafeConstructor(), new CustomRepresenter()).loadAll(content);
+ }
+
public static class CustomRepresenter extends Representer {
protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
index befc7a7..f8e6f68 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
@@ -21,14 +21,21 @@
import org.apache.dubbo.admin.common.exception.ConfigurationException;
import org.apache.dubbo.admin.common.util.Constants;
import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
+import org.apache.dubbo.admin.registry.mapping.ServiceMapping;
+import org.apache.dubbo.admin.registry.mapping.impl.NoOpServiceMapping;
import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
import org.apache.dubbo.admin.registry.metadata.impl.NoOpMetadataCollector;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.metadata.MappingListener;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.RegistryFactory;
+import org.apache.dubbo.registry.RegistryService;
+import org.apache.dubbo.registry.client.ServiceDiscovery;
+import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -37,6 +44,7 @@
import java.util.Arrays;
import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
+import static org.apache.dubbo.registry.client.ServiceDiscoveryFactory.getExtension;
@Configuration
public class ConfigCenter {
@@ -85,7 +93,8 @@
private URL registryUrl;
private URL metadataUrl;
-
+ @Autowired
+ private MappingListener mappingListener;
/*
* generate dynamic configuration client
@@ -130,7 +139,7 @@
/*
* generate registry client
*/
- @Bean
+ @Bean("dubboRegistry")
@DependsOn("governanceConfiguration")
Registry getRegistry() {
Registry registry = null;
@@ -148,7 +157,7 @@
/*
* generate metadata client
*/
- @Bean
+ @Bean("metaDataCollector")
@DependsOn("governanceConfiguration")
MetaDataCollector getMetadataCollector() {
MetaDataCollector metaDataCollector = new NoOpMetadataCollector();
@@ -168,6 +177,30 @@
return metaDataCollector;
}
+
+ @Bean(destroyMethod = "destroy")
+ @DependsOn("dubboRegistry")
+ ServiceDiscovery getServiceDiscoveryRegistry() throws Exception {
+ URL registryURL = registryUrl.setPath(RegistryService.class.getName());
+ ServiceDiscoveryFactory factory = getExtension(registryURL);
+ ServiceDiscovery serviceDiscovery = factory.getServiceDiscovery(registryURL);
+ serviceDiscovery.initialize(registryURL);
+ return serviceDiscovery;
+ }
+
+ @Bean
+ @DependsOn("metaDataCollector")
+ ServiceMapping getServiceMapping() {
+ ServiceMapping serviceMapping = new NoOpServiceMapping();
+ if (metadataUrl == null) {
+ return serviceMapping;
+ }
+ serviceMapping = ExtensionLoader.getExtensionLoader(ServiceMapping.class).getExtension(metadataUrl.getProtocol());
+ serviceMapping.addMappingListener(mappingListener);
+ serviceMapping.init(metadataUrl);
+ return serviceMapping;
+ }
+
public static String removerConfigKey(String properties) {
String[] split = properties.split("=");
String[] address = new String[split.length - 1];
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java
new file mode 100644
index 0000000..9f3136c
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java
@@ -0,0 +1,110 @@
+/*
+ * 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.admin.controller;
+
+import org.apache.dubbo.admin.annotation.Authority;
+import org.apache.dubbo.admin.common.exception.ParamValidationException;
+import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
+import org.apache.dubbo.admin.common.exception.VersionValidationException;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.model.dto.MeshRouteDTO;
+import org.apache.dubbo.admin.service.MeshRouteService;
+import org.apache.dubbo.admin.service.ProviderService;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Authority(needLogin = true)
+@RestController
+@RequestMapping("/api/{env}/rules/route/mesh")
+public class MeshRouteController {
+
+ private final MeshRouteService meshRouteService;
+
+ private final ProviderService providerService;
+
+ public MeshRouteController(MeshRouteService meshRouteService, ProviderService providerService) {
+ this.meshRouteService = meshRouteService;
+ this.providerService = providerService;
+ }
+
+ @RequestMapping(method = RequestMethod.POST)
+ @ResponseStatus(HttpStatus.CREATED)
+ public boolean createMeshRoute(@RequestBody MeshRouteDTO meshRoute, @PathVariable String env) {
+ String app = meshRoute.getApplication();
+ if (StringUtils.isEmpty(app)) {
+ throw new ParamValidationException("app is Empty!");
+ }
+ if (providerService.findVersionInApplication(app).startsWith("2")) {
+ throw new VersionValidationException("dubbo 2.x does not support mesh route");
+ }
+
+ return meshRouteService.createMeshRule(meshRoute);
+ }
+
+ @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
+ public boolean updateRule(@PathVariable String id, @RequestBody MeshRouteDTO meshRoute, @PathVariable String env) {
+ id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
+ if (meshRouteService.findMeshRoute(id) == null) {
+ throw new ResourceNotFoundException("can not find mesh route, Id: " + id);
+ }
+ meshRoute.setId(id);
+ return meshRouteService.updateMeshRule(meshRoute);
+ }
+
+ @RequestMapping(method = RequestMethod.GET)
+ public List<MeshRouteDTO> searchRoutes(@RequestParam String application, @PathVariable String env) {
+ if (StringUtils.isBlank(application)) {
+ throw new ParamValidationException("application is required.");
+ }
+ List<MeshRouteDTO> result = new ArrayList<>();
+
+ MeshRouteDTO meshRoute = meshRouteService.findMeshRoute(application);
+ if (meshRoute != null) {
+ result.add(meshRoute);
+ }
+ return result;
+ }
+
+ @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+ public MeshRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
+ id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
+ MeshRouteDTO meshRoute = meshRouteService.findMeshRoute(id);
+ if (meshRoute == null) {
+ throw new ResourceNotFoundException("Unknown ID!");
+ }
+ return meshRoute;
+ }
+
+ @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
+ public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
+ id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
+ return meshRouteService.deleteMeshRule(id);
+ }
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
index 4a9df1a..bfd801a 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
@@ -103,9 +103,16 @@
if (metadata != null) {
try {
// for dubbo version under 2.7, this metadata will represent as IP address, like 10.0.0.1.
- // So the json conversion will fail.
- FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class);
- serviceDetailDTO.setMetadata(serviceDefinition);
+ // So the json conversion will fail.
+ String release = providerService.findVersionInApplication(application);
+ // serialization compatible 2.x version
+ if (release.startsWith("2")) {
+ org.apache.dubbo.admin.model.domain.FullServiceDefinition serviceDefinition = gson.fromJson(metadata, org.apache.dubbo.admin.model.domain.FullServiceDefinition.class);
+ serviceDetailDTO.setMetadata(serviceDefinition);
+ } else {
+ FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class);
+ serviceDetailDTO.setMetadata(serviceDefinition);
+ }
} catch (JsonParseException e) {
throw new VersionValidationException("dubbo 2.6 does not support metadata");
}
@@ -122,6 +129,11 @@
return new HashSet<>(providerService.findServices());
}
+ @RequestMapping(value = "/applications/instance", method = RequestMethod.GET)
+ public Set<String> allInstanceServices(@PathVariable String env) {
+ return new HashSet<>(providerService.findInstanceApplications());
+ }
+
@RequestMapping(value = "/applications", method = RequestMethod.GET)
public Set<String> allApplications(@PathVariable String env) {
return providerService.findApplications();
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
index cea1708..ca3ad49 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
@@ -23,6 +23,7 @@
import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.util.ConvertUtil;
import org.apache.dubbo.admin.common.util.ServiceTestUtil;
+import org.apache.dubbo.admin.common.util.ServiceTestV3Util;
import org.apache.dubbo.admin.model.domain.MethodMetadata;
import org.apache.dubbo.admin.model.dto.ServiceTestDTO;
import org.apache.dubbo.admin.service.ProviderService;
@@ -71,13 +72,29 @@
MethodMetadata methodMetadata = null;
if (metadata != null) {
Gson gson = new Gson();
- FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class);
- List<MethodDefinition> methods = serviceDefinition.getMethods();
- if (methods != null) {
- for (MethodDefinition m : methods) {
- if (ServiceTestUtil.sameMethod(m, method)) {
- methodMetadata = ServiceTestUtil.generateMethodMeta(serviceDefinition, m);
- break;
+ String release = providerService.findVersionInApplication(application);
+ if (release.startsWith("2.")) {
+ org.apache.dubbo.admin.model.domain.FullServiceDefinition serviceDefinition = gson.fromJson(metadata,
+ org.apache.dubbo.admin.model.domain.FullServiceDefinition.class);
+ List<org.apache.dubbo.admin.model.domain.MethodDefinition> methods = serviceDefinition.getMethods();
+ if (methods != null) {
+ for (org.apache.dubbo.admin.model.domain.MethodDefinition m : methods) {
+ if (ServiceTestUtil.sameMethod(m, method)) {
+ methodMetadata = ServiceTestUtil.generateMethodMeta(serviceDefinition, m);
+ break;
+ }
+ }
+ }
+ } else {
+ FullServiceDefinition serviceDefinition = gson.fromJson(metadata,
+ FullServiceDefinition.class);
+ List<MethodDefinition> methods = serviceDefinition.getMethods();
+ if (methods != null) {
+ for (MethodDefinition m : methods) {
+ if (ServiceTestV3Util.sameMethod(m, method)) {
+ methodMetadata = ServiceTestV3Util.generateMethodMeta(serviceDefinition, m);
+ break;
+ }
}
}
}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java
index 84a7940..82e5031 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java
@@ -17,8 +17,10 @@
package org.apache.dubbo.admin.controller;
import org.apache.dubbo.admin.annotation.Authority;
+import org.apache.dubbo.admin.authentication.LoginAuthentication;
import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.common.extension.ExtensionLoader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -29,8 +31,10 @@
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
+import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -49,15 +53,26 @@
private long sessionTimeoutMilli;
@RequestMapping(value = "/login", method = RequestMethod.GET)
- public String login(@RequestParam String userName, @RequestParam String password) {
- if (StringUtils.isBlank(rootUserName) || (rootUserName.equals(userName) && rootUserPassword.equals(password))) {
- UUID uuid = UUID.randomUUID();
- String token = uuid.toString();
- User user = new User();
- user.setUserName(userName);
- user.setLastUpdateTime(System.currentTimeMillis());
- tokenMap.put(token, user);
- return token;
+ public String login(HttpServletRequest httpServletRequest, @RequestParam String userName, @RequestParam String password) {
+ ExtensionLoader<LoginAuthentication> extensionLoader = ExtensionLoader.getExtensionLoader(LoginAuthentication.class);
+ Set<LoginAuthentication> supportedExtensionInstances = extensionLoader.getSupportedExtensionInstances();
+ Iterator<LoginAuthentication> iterator = supportedExtensionInstances.iterator();
+ boolean flag = true;
+ if (iterator == null) {
+ if (StringUtils.isBlank(rootUserName) || (rootUserName.equals(userName) && rootUserPassword.equals(password))) {
+ return creatToken(rootUserName);
+ }
+ }
+ while (iterator.hasNext()) {
+ LoginAuthentication loginAuthentication = iterator.next();
+ boolean b = loginAuthentication.authentication(httpServletRequest, userName, password);
+ flag = b & flag;
+ if (flag == false) {
+ break;
+ }
+ }
+ if (flag) {
+ return creatToken(userName);
}
return null;
}
@@ -97,4 +112,13 @@
}
}
+ public String creatToken(String userName) {
+ UUID uuid = UUID.randomUUID();
+ String token = uuid.toString();
+ User user = new User();
+ user.setUserName(userName);
+ user.setLastUpdateTime(System.currentTimeMillis());
+ tokenMap.put(token, user);
+ return token;
+ }
}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/FullServiceDefinition.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/FullServiceDefinition.java
new file mode 100644
index 0000000..54dc59b
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/FullServiceDefinition.java
@@ -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.admin.model.domain;
+
+import java.util.Map;
+
+/**
+ * copy from {@link org.apache.dubbo.metadata.definition.model.FullServiceDefinition} compatible 2.x version
+ */
+public class FullServiceDefinition extends ServiceDefinition {
+ private Map<String, String> parameters;
+
+ public Map<String, String> getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(Map<String, String> parameters) {
+ this.parameters = parameters;
+ }
+
+ public String toString() {
+ return "FullServiceDefinition{" +
+ "parameters=" + parameters +
+ "} " + super.toString();
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MethodDefinition.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MethodDefinition.java
new file mode 100644
index 0000000..1c0b8fe
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MethodDefinition.java
@@ -0,0 +1,108 @@
+/*
+ * 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.admin.model.domain;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * copy from {@link org.apache.dubbo.metadata.definition.model.MethodDefinition} compatible 2.x version
+ */
+public class MethodDefinition {
+
+ private String name;
+ private String[] parameterTypes;
+ private String returnType;
+ private List<TypeDefinition> parameters;
+ private List<String> annotations;
+
+ public MethodDefinition() {
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public List<TypeDefinition> getParameters() {
+ if (this.parameters == null) {
+ this.parameters = new ArrayList();
+ }
+
+ return this.parameters;
+ }
+
+ public String[] getParameterTypes() {
+ return this.parameterTypes;
+ }
+
+ public String getReturnType() {
+ return this.returnType;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setParameters(List<TypeDefinition> parameters) {
+ this.parameters = parameters;
+ }
+
+ public void setParameterTypes(String[] parameterTypes) {
+ this.parameterTypes = TypeDefinition.formatTypes(parameterTypes);
+ }
+
+ public void setReturnType(String returnType) {
+ this.returnType = TypeDefinition.formatType(returnType);
+ }
+
+ public List<String> getAnnotations() {
+ if (this.annotations == null) {
+ this.annotations = Collections.emptyList();
+ }
+
+ return this.annotations;
+ }
+
+ public void setAnnotations(List<String> annotations) {
+ this.annotations = annotations;
+ }
+
+ public String toString() {
+ return "MethodDefinition [name=" + this.name + ", parameterTypes=" + Arrays.toString(this.parameterTypes) + ", returnType=" + this.returnType + "]";
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ } else if (!(o instanceof MethodDefinition)) {
+ return false;
+ } else {
+ MethodDefinition that = (MethodDefinition) o;
+ return Objects.equals(this.getName(), that.getName()) && Arrays.equals(this.getParameterTypes(), that.getParameterTypes()) && Objects.equals(this.getReturnType(), that.getReturnType()) && Objects.equals(this.getParameters(), that.getParameters());
+ }
+ }
+
+ public int hashCode() {
+ int result = Objects.hash(new Object[]{this.getName(), this.getReturnType(), this.getParameters()});
+ result = 31 * result + Arrays.hashCode(this.getParameterTypes());
+ return result;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java
index 363872b..2de0ad0 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java
@@ -60,6 +60,8 @@
private List<Override> overrides;
+ private RegistrySource registrySource;
+
public Provider() {
}
@@ -181,6 +183,14 @@
this.overrides = overrides;
}
+ public RegistrySource getRegistrySource() {
+ return registrySource;
+ }
+
+ public void setRegistrySource(RegistrySource registrySource) {
+ this.registrySource = registrySource;
+ }
+
public URL toUrl() {
Map<String, String> serviceName2Map = ConvertUtil.serviceName2Map(getService());
/*if(!serviceName2Map.containsKey(Constants.INTERFACE_KEY)) {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java
new file mode 100644
index 0000000..e54644c
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java
@@ -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.admin.model.domain;
+
+public enum RegistrySource {
+
+ INTERFACE,
+
+ INSTANCE
+
+}
\ No newline at end of file
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/ServiceDefinition.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/ServiceDefinition.java
new file mode 100644
index 0000000..9205ac7
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/ServiceDefinition.java
@@ -0,0 +1,133 @@
+/*
+ * 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.admin.model.domain;
+
+import org.apache.dubbo.metadata.definition.util.ClassUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * copy from {@link org.apache.dubbo.metadata.definition.model.ServiceDefinition} compatible 2.x version
+ */
+public class ServiceDefinition {
+
+ /**
+ * the canonical name of interface
+ *
+ * @see Class#getCanonicalName()
+ */
+ private String canonicalName;
+
+ /**
+ * the location of class file
+ *
+ * @see ClassUtils#getCodeSource(Class)
+ */
+ private String codeSource;
+
+ private List<MethodDefinition> methods;
+
+ /**
+ * the definitions of type
+ */
+ private List<TypeDefinition> types;
+
+ /**
+ * the definitions of annotations
+ */
+ private List<String> annotations;
+
+ public String getCanonicalName() {
+ return canonicalName;
+ }
+
+ public String getCodeSource() {
+ return codeSource;
+ }
+
+ public List<MethodDefinition> getMethods() {
+ if (methods == null) {
+ methods = new ArrayList<>();
+ }
+ return methods;
+ }
+
+ public List<TypeDefinition> getTypes() {
+ if (types == null) {
+ types = new ArrayList<>();
+ }
+ return types;
+ }
+
+ public String getUniqueId() {
+ return canonicalName + "@" + codeSource;
+ }
+
+ public void setCanonicalName(String canonicalName) {
+ this.canonicalName = canonicalName;
+ }
+
+ public void setCodeSource(String codeSource) {
+ this.codeSource = codeSource;
+ }
+
+ public void setMethods(List<MethodDefinition> methods) {
+ this.methods = methods;
+ }
+
+ public void setTypes(List<TypeDefinition> types) {
+ this.types = types;
+ }
+
+ public List<String> getAnnotations() {
+ if (annotations == null) {
+ annotations = Collections.emptyList();
+ }
+ return annotations;
+ }
+
+ public void setAnnotations(List<String> annotations) {
+ this.annotations = annotations;
+ }
+
+ public String toString() {
+ return "ServiceDefinition [canonicalName=" + canonicalName + ", codeSource=" + codeSource + ", methods="
+ + methods + "]";
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ServiceDefinition)) {
+ return false;
+ }
+ ServiceDefinition that = (ServiceDefinition) o;
+ return Objects.equals(getCanonicalName(), that.getCanonicalName()) &&
+ Objects.equals(getCodeSource(), that.getCodeSource()) &&
+ Objects.equals(getMethods(), that.getMethods()) &&
+ Objects.equals(getTypes(), that.getTypes());
+ }
+
+ public int hashCode() {
+ return Objects.hash(getCanonicalName(), getCodeSource(), getMethods(), getTypes());
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/TypeDefinition.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/TypeDefinition.java
new file mode 100644
index 0000000..71ed8fa
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/TypeDefinition.java
@@ -0,0 +1,161 @@
+/*
+ * 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.admin.model.domain;
+
+import org.apache.dubbo.common.utils.StringUtils;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+
+/**
+ * copy from {@link org.apache.dubbo.metadata.definition.model.TypeDefinition} compatible 2.x version
+ */
+public class TypeDefinition implements Serializable {
+ private String id;
+ private String type;
+ @SerializedName("items")
+ private List<TypeDefinition> items;
+ @SerializedName("enum")
+ private List<String> enums;
+ private String $ref;
+ private Map<String, TypeDefinition> properties;
+ private String typeBuilderName;
+
+ public TypeDefinition() {
+ }
+
+ public TypeDefinition(String type) {
+ this.setType(type);
+ }
+
+ public static String[] formatTypes(String[] types) {
+ String[] newTypes = new String[types.length];
+
+ for (int i = 0; i < types.length; ++i) {
+ newTypes[i] = formatType(types[i]);
+ }
+
+ return newTypes;
+ }
+
+ public static String formatType(String type) {
+ return isGenericType(type) ? formatGenericType(type) : type;
+ }
+
+ private static String formatGenericType(String type) {
+ return StringUtils.replace(type, ", ", ",");
+ }
+
+ private static boolean isGenericType(String type) {
+ return type.contains("<") && type.contains(">");
+ }
+
+ public String get$ref() {
+ return this.$ref;
+ }
+
+ public List<String> getEnums() {
+ if (this.enums == null) {
+ this.enums = new ArrayList();
+ }
+
+ return this.enums;
+ }
+
+ public String getId() {
+ return this.id;
+ }
+
+ public List<TypeDefinition> getItems() {
+ if (this.items == null) {
+ this.items = new ArrayList();
+ }
+
+ return this.items;
+ }
+
+ public Map<String, TypeDefinition> getProperties() {
+ if (this.properties == null) {
+ this.properties = new HashMap();
+ }
+
+ return this.properties;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public String getTypeBuilderName() {
+ return this.typeBuilderName;
+ }
+
+ public void set$ref(String $ref) {
+ this.$ref = $ref;
+ }
+
+ public void setEnums(List<String> enums) {
+ this.enums = enums;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public void setItems(List<TypeDefinition> items) {
+ this.items = items;
+ }
+
+ public void setProperties(Map<String, TypeDefinition> properties) {
+ this.properties = properties;
+ }
+
+ public void setType(String type) {
+ this.type = formatType(type);
+ }
+
+ public void setTypeBuilderName(String typeBuilderName) {
+ this.typeBuilderName = typeBuilderName;
+ }
+
+ public String toString() {
+ return "TypeDefinition [id=" + this.id + ", type=" + this.type + ", properties=" + this.properties + ", $ref=" + this.$ref + "]";
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ } else if (!(o instanceof TypeDefinition)) {
+ return false;
+ } else {
+ TypeDefinition that = (TypeDefinition) o;
+ return Objects.equals(this.getId(), that.getId()) && Objects.equals(this.getType(), that.getType()) && Objects.equals(this.getItems(), that.getItems()) && Objects.equals(this.getEnums(), that.getEnums()) && Objects.equals(this.get$ref(), that.get$ref()) && Objects.equals(this.getProperties(), that.getProperties());
+ }
+ }
+
+ public int hashCode() {
+ return Objects.hash(new Object[]{this.getId(), this.getType(), this.getItems(), this.getEnums(), this.get$ref(), this.getProperties()});
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java
new file mode 100644
index 0000000..349c3c0
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java
@@ -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.admin.model.dto;
+
+public class MeshRouteDTO extends BaseDTO{
+
+ private String meshRule;
+
+ public String getMeshRule() {
+ return meshRule;
+ }
+
+ public void setMeshRule(String meshRule) {
+ this.meshRule = meshRule;
+ }
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
index 0202526..cd15916 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
@@ -17,15 +17,17 @@
package org.apache.dubbo.admin.model.dto;
+import org.apache.dubbo.admin.model.domain.RegistrySource;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;
-public class ServiceDTO implements Comparable<ServiceDTO>{
+public class ServiceDTO implements Comparable<ServiceDTO> {
private String service;
private String appName;
private String group;
private String version;
+ private RegistrySource registrySource;
public String getService() {
return service;
@@ -59,6 +61,14 @@
this.version = version;
}
+ public RegistrySource getRegistrySource() {
+ return registrySource;
+ }
+
+ public void setRegistrySource(RegistrySource registrySource) {
+ this.registrySource = registrySource;
+ }
+
@Override
public int compareTo(ServiceDTO o) {
int result = StringUtils.trimToEmpty(appName).compareTo(StringUtils.trimToEmpty(o.getAppName()));
@@ -70,6 +80,9 @@
if (result == 0) {
result = StringUtils.trimToEmpty(version).compareTo(StringUtils.trimToEmpty(o.getVersion()));
}
+ if (result == 0) {
+ result = registrySource.compareTo(o.registrySource);
+ }
}
return result;
}
@@ -84,11 +97,11 @@
}
ServiceDTO that = (ServiceDTO) o;
return Objects.equals(service, that.service) && Objects.equals(appName, that.appName) && Objects
- .equals(group, that.group) && Objects.equals(version, that.version);
+ .equals(group, that.group) && Objects.equals(version, that.version) && Objects.equals(registrySource, that.registrySource);
}
@Override
public int hashCode() {
- return Objects.hash(service, appName, group, version);
+ return Objects.hash(service, appName, group, version, registrySource);
}
}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
index 1ef4beb..d15a7bf 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
@@ -19,7 +19,6 @@
import org.apache.dubbo.admin.model.domain.Consumer;
import org.apache.dubbo.admin.model.domain.Provider;
-import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import java.util.List;
@@ -30,7 +29,7 @@
private String service;
private String application;
- FullServiceDefinition metadata;
+ Object metadata;
public String getService() {
return service;
@@ -64,11 +63,11 @@
this.consumers = consumers;
}
- public FullServiceDefinition getMetadata() {
+ public Object getMetadata() {
return metadata;
}
- public void setMetadata(FullServiceDefinition metadata) {
+ public void setMetadata(Object metadata) {
this.metadata = metadata;
}
}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java
new file mode 100644
index 0000000..94e7afd
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java
@@ -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.admin.model.store.mesh;
+
+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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java
new file mode 100644
index 0000000..8c99863
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java
@@ -0,0 +1,56 @@
+/*
+ * 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.admin.model.store.mesh;
+
+
+import org.apache.dubbo.admin.model.store.mesh.destination.DestinationRule;
+import org.apache.dubbo.admin.model.store.mesh.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;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java
new file mode 100644
index 0000000..71a5c43
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java
@@ -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.admin.model.store.mesh.destination;
+
+
+public class ConnectionPoolSettings {
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java
new file mode 100644
index 0000000..9b0d8c6
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java
@@ -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.admin.model.store.mesh.destination;
+
+
+import org.apache.dubbo.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java
new file mode 100644
index 0000000..470b7c4
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java
@@ -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.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java
new file mode 100644
index 0000000..66b6fa4
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java
@@ -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.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java
new file mode 100644
index 0000000..1cc05ce
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java
@@ -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.admin.model.store.mesh.destination;
+
+
+public class TCPSettings {
+ private int maxConnections;
+ private int connectTimeout;
+ private TcpKeepalive tcpKeepalive;
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java
new file mode 100644
index 0000000..aa48bf6
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java
@@ -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.admin.model.store.mesh.destination;
+
+
+public class TcpKeepalive {
+ private int probes;
+ private int time;
+ private int interval;
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java
new file mode 100644
index 0000000..bda74d6
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java
@@ -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.admin.model.store.mesh.destination;
+
+
+import org.apache.dubbo.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java
new file mode 100644
index 0000000..e0c11e4
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java
@@ -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.admin.model.store.mesh.destination.loadbalance;
+
+
+public class ConsistentHashLB {
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java
new file mode 100644
index 0000000..5a5a1ec
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java
@@ -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.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java
new file mode 100644
index 0000000..b8b13ec
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java
@@ -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.admin.model.store.mesh.destination.loadbalance;
+
+
+public enum SimpleLB {
+ ROUND_ROBIN,
+ LEAST_CONN,
+ RANDOM,
+ PASSTHROUGH
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java
new file mode 100644
index 0000000..59dcd3c
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.admin.model.store.mesh.virtualservice;
+
+
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.DoubleMatch;
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.DubboAttachmentMatch;
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.DubboMethodMatch;
+import org.apache.dubbo.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java
new file mode 100644
index 0000000..9747b6b
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java
@@ -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.admin.model.store.mesh.virtualservice;
+
+
+import org.apache.dubbo.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java
new file mode 100644
index 0000000..1b576d5
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java
@@ -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.admin.model.store.mesh.virtualservice;
+
+
+import org.apache.dubbo.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java
new file mode 100644
index 0000000..c5798d8
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java
@@ -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.admin.model.store.mesh.virtualservice;
+
+
+import org.apache.dubbo.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java
new file mode 100644
index 0000000..c4eab8d
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java
@@ -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.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java
new file mode 100644
index 0000000..781308e
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java
@@ -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.admin.model.store.mesh.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;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java
new file mode 100644
index 0000000..95ede77
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java
@@ -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.admin.model.store.mesh.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;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java
new file mode 100644
index 0000000..d354157
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java
@@ -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.admin.model.store.mesh.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;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java
new file mode 100644
index 0000000..89ab4d6
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java
@@ -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.admin.model.store.mesh.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;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java
new file mode 100644
index 0000000..00d09db
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java
@@ -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.admin.model.store.mesh.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;
+ }
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java
new file mode 100644
index 0000000..37f1da4
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java
@@ -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.admin.model.store.mesh.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;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java
new file mode 100644
index 0000000..8e0f991
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java
@@ -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.admin.model.store.mesh.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 +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java
new file mode 100644
index 0000000..c448895
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java
@@ -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.admin.model.store.mesh.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 +
+ '}';
+ }
+}
+
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java
new file mode 100644
index 0000000..b3289e2
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java
@@ -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.admin.model.store.mesh.virtualservice.match;
+
+
+public class ListBoolMatch {
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java
new file mode 100644
index 0000000..51c4b44
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java
@@ -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.admin.model.store.mesh.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;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java
new file mode 100644
index 0000000..d8f935f
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java
@@ -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.admin.model.store.mesh.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;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java
new file mode 100644
index 0000000..5cd7465
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java
@@ -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.admin.model.store.mesh.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 + '\'' +
+ '}';
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AddressChangeListener.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AddressChangeListener.java
new file mode 100644
index 0000000..076bb56
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AddressChangeListener.java
@@ -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.admin.registry.mapping;
+
+import org.apache.dubbo.common.URL;
+
+import java.util.List;
+
+public interface AddressChangeListener {
+
+ /**
+ * notify instance address url change
+ * @param protocolServiceKey {group}/{path/interfaceName}:{version}:protocol
+ * @param urls instance address url
+ */
+ void notifyAddressChanged(String protocolServiceKey, List<URL> urls);
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java
new file mode 100644
index 0000000..56db6e3
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java
@@ -0,0 +1,131 @@
+/*
+ * 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.admin.registry.mapping;
+
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.service.impl.InstanceRegistryCache;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.metadata.MappingChangedEvent;
+import org.apache.dubbo.metadata.MappingListener;
+import org.apache.dubbo.registry.client.InstanceAddressURL;
+import org.apache.dubbo.registry.client.ServiceDiscovery;
+import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
+import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
+
+import com.google.common.collect.Sets;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Collectors;
+
+@Component
+public class AdminMappingListener implements MappingListener {
+
+ private static final URL CONSUMER_URL = new URL(Constants.ADMIN_PROTOCOL, NetUtils.getLocalHost(), 0, "",
+ Constants.INTERFACE_KEY, Constants.ANY_VALUE,
+ Constants.GROUP_KEY, Constants.ANY_VALUE,
+ Constants.VERSION_KEY, Constants.ANY_VALUE,
+ Constants.CLASSIFIER_KEY, Constants.ANY_VALUE,
+ Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY + ","
+ + Constants.CONSUMERS_CATEGORY + ","
+ + Constants.ROUTERS_CATEGORY + ","
+ + Constants.CONFIGURATORS_CATEGORY,
+ Constants.ENABLED_KEY, Constants.ANY_VALUE,
+ Constants.CHECK_KEY, String.valueOf(false));
+
+ /* app - listener */
+ private final Map<String, ServiceInstancesChangedListener> serviceListeners = new ConcurrentHashMap<>();
+
+ private final ServiceDiscovery serviceDiscovery;
+
+ private final InstanceRegistryCache instanceRegistryCache;
+
+ public AdminMappingListener(ServiceDiscovery serviceDiscovery, InstanceRegistryCache instanceRegistryCache) {
+ this.serviceDiscovery = serviceDiscovery;
+ this.instanceRegistryCache = instanceRegistryCache;
+ }
+
+ @Override
+ public void onEvent(MappingChangedEvent event) {
+ Set<String> apps = event.getApps();
+ if (CollectionUtils.isEmpty(apps)) {
+ return;
+ }
+ for (String serviceName : apps) {
+ ServiceInstancesChangedListener serviceInstancesChangedListener = serviceListeners.get(serviceName);
+ if (serviceInstancesChangedListener == null) {
+ synchronized (this) {
+ serviceInstancesChangedListener = serviceListeners.get(serviceName);
+ if (serviceInstancesChangedListener == null) {
+ AddressChangeListener addressChangeListener = new DefaultAddressChangeListener(serviceName, instanceRegistryCache);
+ serviceInstancesChangedListener = new AdminServiceInstancesChangedListener(Sets.newHashSet(serviceName), serviceDiscovery, addressChangeListener);
+ serviceInstancesChangedListener.setUrl(CONSUMER_URL);
+ List<ServiceInstance> serviceInstances = serviceDiscovery.getInstances(serviceName);
+ if (CollectionUtils.isNotEmpty(serviceInstances)) {
+ serviceInstancesChangedListener.onEvent(new ServiceInstancesChangedEvent(serviceName, serviceInstances));
+ }
+ serviceListeners.put(serviceName, serviceInstancesChangedListener);
+ serviceInstancesChangedListener.setUrl(CONSUMER_URL);
+ serviceDiscovery.addServiceInstancesChangedListener(serviceInstancesChangedListener);
+ }
+ }
+ }
+ }
+ }
+
+ private static class DefaultAddressChangeListener implements AddressChangeListener {
+
+ private String serviceName;
+
+ private InstanceRegistryCache instanceRegistryCache;
+
+ public DefaultAddressChangeListener(String serviceName, InstanceRegistryCache instanceRegistryCache) {
+ this.serviceName = serviceName;
+ this.instanceRegistryCache = instanceRegistryCache;
+ }
+
+ @Override
+ public void notifyAddressChanged(String protocolServiceKey, List<URL> urls) {
+ String serviceKey = removeProtocol(protocolServiceKey);
+ ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appServiceMap = instanceRegistryCache.computeIfAbsent(Constants.PROVIDERS_CATEGORY, key -> new ConcurrentHashMap<>());
+ Map<String, List<InstanceAddressURL>> serviceMap = appServiceMap.computeIfAbsent(serviceName, key -> new ConcurrentHashMap<>());
+ if (CollectionUtils.isEmpty(urls)) {
+ serviceMap.remove(serviceKey);
+ } else {
+ List<InstanceAddressURL> instanceAddressUrls = urls.stream().map(url -> (InstanceAddressURL) url).collect(Collectors.toList());
+ serviceMap.put(serviceKey, instanceAddressUrls);
+ }
+ }
+
+ private String removeProtocol(String protocolServiceKey) {
+ int index = protocolServiceKey.lastIndexOf(":");
+ if (index == -1) {
+ return protocolServiceKey;
+ }
+ return protocolServiceKey.substring(0, index);
+ }
+ }
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminServiceInstancesChangedListener.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminServiceInstancesChangedListener.java
new file mode 100644
index 0000000..1afde55
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminServiceInstancesChangedListener.java
@@ -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.admin.registry.mapping;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.registry.client.ServiceDiscovery;
+import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class AdminServiceInstancesChangedListener extends ServiceInstancesChangedListener {
+
+ private AddressChangeListener addressChangeListener;
+
+ private Map<String, Object> oldServiceUrls;
+
+ public AdminServiceInstancesChangedListener(Set<String> serviceNames, ServiceDiscovery serviceDiscovery, AddressChangeListener addressChangeListener) {
+ super(serviceNames, serviceDiscovery);
+ this.addressChangeListener = addressChangeListener;
+ oldServiceUrls = new HashMap<>();
+ }
+
+ protected void notifyAddressChanged() {
+ oldServiceUrls.keySet().stream()
+ .filter(protocolServiceKey -> !serviceUrls.containsKey(protocolServiceKey))
+ .forEach(protocolServiceKey -> addressChangeListener.notifyAddressChanged(protocolServiceKey, new ArrayList<>()));
+ serviceUrls.forEach((protocolServiceKey, urls) -> addressChangeListener.notifyAddressChanged(protocolServiceKey, (List<URL>) urls));
+
+ oldServiceUrls = serviceUrls;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/ServiceMapping.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/ServiceMapping.java
new file mode 100644
index 0000000..6559a29
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/ServiceMapping.java
@@ -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.admin.registry.mapping;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.metadata.MappingListener;
+
+/**
+ * listen all mapping group service
+ */
+@SPI("zookeeper")
+public interface ServiceMapping {
+
+ void init(URL url);
+
+ void listenerAll();
+
+ void addMappingListener(MappingListener listener);
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NoOpServiceMapping.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NoOpServiceMapping.java
new file mode 100644
index 0000000..845efa2
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NoOpServiceMapping.java
@@ -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.admin.registry.mapping.impl;
+
+import org.apache.dubbo.admin.registry.mapping.ServiceMapping;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.metadata.MappingListener;
+
+public class NoOpServiceMapping implements ServiceMapping {
+
+ @Override
+ public void init(URL url) {
+
+ }
+
+ @Override
+ public void listenerAll() {
+
+ }
+
+ @Override
+ public void addMappingListener(MappingListener listener) {
+
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java
new file mode 100644
index 0000000..799c040
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java
@@ -0,0 +1,93 @@
+/*
+ * 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.admin.registry.mapping.impl;
+
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.registry.mapping.ServiceMapping;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.ConcurrentHashSet;
+import org.apache.dubbo.metadata.MappingChangedEvent;
+import org.apache.dubbo.metadata.MappingListener;
+import org.apache.dubbo.remoting.zookeeper.ZookeeperClient;
+import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.ServiceNameMapping.getAppNames;
+
+
+public class ZookeeperServiceMapping implements ServiceMapping {
+
+ private ZookeeperClient zkClient;
+
+ private final static String MAPPING_PATH = Constants.PATH_SEPARATOR + Constants.DEFAULT_ROOT + Constants.PATH_SEPARATOR + Constants.DEFAULT_MAPPING_GROUP;
+
+ private final Set<MappingListener> listeners = new ConcurrentHashSet<>();
+
+ private final Set<String> anyServices = new ConcurrentHashSet<>();
+
+ @Override
+ public void init(URL url) {
+ ZookeeperTransporter zookeeperTransporter = ZookeeperTransporter.getExtension();
+ zkClient = zookeeperTransporter.connect(url);
+ listenerAll();
+ }
+
+ @Override
+ public void listenerAll() {
+ zkClient.create(MAPPING_PATH, false);
+ List<String> services = zkClient.addChildListener(MAPPING_PATH, (path, currentChildList) -> {
+ for (String child : currentChildList) {
+ if (anyServices.add(child)) {
+ notifyMappingChangedEvent(child);
+ }
+ }
+ });
+ if (CollectionUtils.isNotEmpty(services)) {
+ for (String service : services) {
+ if (anyServices.add(service)) {
+ notifyMappingChangedEvent(service);
+ }
+ }
+ }
+ }
+
+ private void notifyMappingChangedEvent(String service) {
+ if (service.equals(Constants.CONFIGURATORS_CATEGORY) || service.equals(Constants.CONSUMERS_CATEGORY)
+ || service.equals(Constants.PROVIDERS_CATEGORY) || service.equals(Constants.ROUTERS_CATEGORY)) {
+ return;
+ }
+ String servicePath = MAPPING_PATH + Constants.PATH_SEPARATOR + service;
+ String content = zkClient.getContent(servicePath);
+ if (content != null) {
+ Set<String> apps = getAppNames(content);
+ MappingChangedEvent event = new MappingChangedEvent(service, apps);
+ for (MappingListener listener : listeners) {
+ listener.onEvent(event);
+ }
+ }
+ }
+
+ @Override
+ public void addMappingListener(MappingListener listener) {
+ listeners.add(listener);
+ }
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java
new file mode 100644
index 0000000..708dd7e
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java
@@ -0,0 +1,56 @@
+/*
+ * 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.admin.service;
+
+import org.apache.dubbo.admin.model.dto.MeshRouteDTO;
+
+public interface MeshRouteService {
+
+ /**
+ * create mesh rule route
+ *
+ * @param meshRoute dto
+ * @return success
+ */
+ boolean createMeshRule(MeshRouteDTO meshRoute);
+
+ /**
+ * update mesh rule route
+ *
+ * @param meshRoute dto
+ * @return success
+ */
+ boolean updateMeshRule(MeshRouteDTO meshRoute);
+
+ /**
+ * delete mesh rule
+ *
+ * @param id id
+ * @return success
+ */
+ boolean deleteMeshRule(String id);
+
+ /**
+ * find mesh rule by id
+ *
+ * @param id id
+ * @return dto
+ */
+ MeshRouteDTO findMeshRoute(String id);
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/ProviderService.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
index 95d46f8..5417d30 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
@@ -25,26 +25,11 @@
/**
* ProviderService
- *
*/
public interface ProviderService {
void create(Provider provider);
-// void enableProvider(String id);
-
-// void disableProvider(String id);
-
-// void doublingProvider(String id);
-
-// void halvingProvider(String id);
-
- void deleteStaticProvider(String id);
-
- void updateProvider(Provider provider);
-
- Provider findProvider(String id);
-
String getProviderMetaData(MetadataIdentifier providerIdentifier);
/**
@@ -54,18 +39,20 @@
*/
Set<String> findServices();
+ /**
+ * Get all instance registry provider's service name
+ *
+ * @return list of all provider's service name
+ */
+ Set<String> findInstanceApplications();
+
+
String findServiceVersion(String serviceName, String application);
String findVersionInApplication(String application);
List<String> findAddresses();
- List<String> findAddressesByApplication(String application);
-
- List<String> findAddressesByService(String serviceName);
-
- List<String> findApplicationsByServiceName(String serviceName);
-
/**
* Get provider list with specific service name.
*
@@ -74,8 +61,6 @@
*/
List<Provider> findByService(String serviceName);
- List<Provider> findByAppandService(String app, String serviceName);
-
List<Provider> findAll();
/**
@@ -86,8 +71,6 @@
*/
List<Provider> findByAddress(String providerAddress);
- List<String> findServicesByAddress(String providerAddress);
-
Set<String> findApplications();
/**
@@ -100,13 +83,9 @@
List<String> findServicesByApplication(String application);
- List<String> findMethodsByService(String serviceName);
-
- Provider findByServiceAndAddress(String service, String address);
-
/**
* Get a set of service data object.
- *
+ * <p>
* ServiceDTO object contains base information include
* service name , application, group and version.
*
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryCache.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryCache.java
new file mode 100644
index 0000000..0335909
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryCache.java
@@ -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.admin.service;
+
+import java.util.function.Function;
+
+/**
+ * cache registry url
+ */
+public interface RegistryCache<K, V> {
+
+ /**
+ * put cache
+ *
+ * @param key key
+ * @param value value
+ */
+ void put(K key, V value);
+
+ /**
+ * get cache
+ *
+ * @param key key
+ * @return value
+ */
+ V get(K key);
+
+
+ default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+ return null;
+ }
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
index f57cdb3..dab1a43 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
@@ -19,6 +19,8 @@
import org.apache.dubbo.admin.common.util.CoderUtil;
import org.apache.dubbo.admin.common.util.Constants;
import org.apache.dubbo.admin.common.util.Tool;
+import org.apache.dubbo.admin.service.impl.InterfaceRegistryCache;
+import org.apache.dubbo.common.BaseServiceMetadata;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@@ -69,13 +71,11 @@
* ConcurrentMap<category, ConcurrentMap<servicename, Map<MD5, URL>>>
* registryCache
*/
- private final ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> registryCache = new ConcurrentHashMap<>();
@Autowired
private Registry registry;
- public ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> getRegistryCache() {
- return registryCache;
- }
+ @Autowired
+ private InterfaceRegistryCache interfaceRegistryCache;
@EventListener(classes = ApplicationReadyEvent.class)
public void startSubscribe() {
@@ -98,16 +98,19 @@
final Map<String, Map<String, Map<String, URL>>> categories = new HashMap<>();
String interfaceName = null;
for (URL url : urls) {
- String category = url.getParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
+ String category = url.getUrlParam().getParameter(Constants.CATEGORY_KEY);
+ if (category == null) {
+ category = Constants.PROVIDERS_CATEGORY;
+ }
// NOTE: group and version in empty protocol is *
if (Constants.EMPTY_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
- ConcurrentMap<String, Map<String, URL>> services = registryCache.get(category);
+ ConcurrentMap<String, Map<String, URL>> services = interfaceRegistryCache.get(category);
if (services != null) {
- String group = url.getParameter(Constants.GROUP_KEY);
- String version = url.getParameter(Constants.VERSION_KEY);
+ String group = url.getUrlParam().getParameter(Constants.GROUP_KEY);
+ String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
// NOTE: group and version in empty protocol is *
if (!Constants.ANY_VALUE.equals(group) && !Constants.ANY_VALUE.equals(version)) {
- services.remove(url.getServiceKey());
+ services.remove(url.getServiceInterface());
} else {
for (Map.Entry<String, Map<String, URL>> serviceEntry : services.entrySet()) {
String service = serviceEntry.getKey();
@@ -128,7 +131,9 @@
services = new HashMap<>();
categories.put(category, services);
}
- String service = url.getServiceKey();
+ String group = url.getUrlParam().getParameter(Constants.GROUP_KEY);
+ String version = url.getUrlParam().getParameter(Constants.VERSION_KEY);
+ String service = BaseServiceMetadata.buildServiceKey(url.getServiceInterface(), group, version);
Map<String, URL> ids = services.get(service);
if (ids == null) {
ids = new HashMap<>();
@@ -150,10 +155,10 @@
}
for (Map.Entry<String, Map<String, Map<String, URL>>> categoryEntry : categories.entrySet()) {
String category = categoryEntry.getKey();
- ConcurrentMap<String, Map<String, URL>> services = registryCache.get(category);
+ ConcurrentMap<String, Map<String, URL>> services = interfaceRegistryCache.get(category);
if (services == null) {
services = new ConcurrentHashMap<String, Map<String, URL>>();
- registryCache.put(category, services);
+ interfaceRegistryCache.put(category, services);
} else {// Fix map can not be cleared when service is unregistered: when a unique “group/service:version” service is unregistered, but we still have the same services with different version or group, so empty protocols can not be invoked.
Set<String> keys = new HashSet<String>(services.keySet());
for (String key : keys) {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
index f7bae0d..501b13e 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
@@ -18,7 +18,6 @@
import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
-import org.apache.dubbo.admin.service.RegistryServerSync;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@@ -42,10 +41,10 @@
protected MetaDataCollector metaDataCollector;
@Autowired
- private RegistryServerSync sync;
+ private InterfaceRegistryCache interfaceRegistryCache;
- public ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> getRegistryCache() {
- return sync.getRegistryCache();
+ public ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> getInterfaceRegistryCache() {
+ return interfaceRegistryCache.getRegistryCache();
}
}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
index 4a803ed..0d0f2e5 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
@@ -52,7 +52,7 @@
private Map<String, URL> findAllConsumerUrl() {
Map<String, String> filter = new HashMap<String, String>();
filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY);
- return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+ return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
}
@@ -69,7 +69,7 @@
filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY);
filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
- return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+ return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
}
public Map<String, URL> findConsumerUrlByService(String service) {
@@ -77,7 +77,7 @@
filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY);
filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
- return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+ return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
}
@Override
@@ -85,7 +85,7 @@
Map<String, String> filter = new HashMap<>();
filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY);
filter.put(Constants.APPLICATION_KEY, application);
- Map<String, URL> stringURLMap = SyncUtils.filterFromCategory(getRegistryCache(), filter);
+ Map<String, URL> stringURLMap = SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
if (stringURLMap == null || stringURLMap.isEmpty()) {
throw new ParamValidationException("there is no consumer for application: " + application);
}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java
new file mode 100644
index 0000000..9f1b5ac
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java
@@ -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.admin.service.impl;
+
+import org.apache.dubbo.admin.service.RegistryCache;
+import org.apache.dubbo.registry.client.InstanceAddressURL;
+
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
+/**
+ * instance registry url {@link InstanceAddressURL} cache
+ * key --> category,value --> ConcurrentMap<appName, Map<serviceKey, List<InstanceAddressURL>>>
+ */
+@Component
+public class InstanceRegistryCache implements RegistryCache<String, ConcurrentMap<String, Map<String, List<InstanceAddressURL>>>> {
+
+ private final ConcurrentMap<String, ConcurrentMap<String, Map<String, List<InstanceAddressURL>>>> registryCache = new ConcurrentHashMap<>();
+
+ @Override
+ public void put(String key, ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> value) {
+ registryCache.put(key, value);
+ }
+
+ @Override
+ public ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> get(String key) {
+ return registryCache.get(key);
+ }
+
+ @Override
+ public ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> computeIfAbsent(String key,
+ Function<? super String, ? extends ConcurrentMap<String, Map<String, List<InstanceAddressURL>>>> mappingFunction) {
+ return registryCache.computeIfAbsent(key, mappingFunction);
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java
new file mode 100644
index 0000000..aae6e65
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java
@@ -0,0 +1,155 @@
+/*
+ * 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.admin.service.impl;
+
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.admin.model.domain.RegistrySource;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.metadata.MetadataInfo;
+import org.apache.dubbo.registry.client.InstanceAddressURL;
+import org.apache.dubbo.registry.client.ServiceInstance;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Collectors;
+
+@Component
+public class InstanceRegistryQueryHelper {
+
+ private final InstanceRegistryCache instanceRegistryCache;
+
+ public InstanceRegistryQueryHelper(InstanceRegistryCache instanceRegistryCache) {
+ this.instanceRegistryCache = instanceRegistryCache;
+ }
+
+
+ public Set<String> findServices() {
+ Set<String> services = Sets.newHashSet();
+ ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+ if (appInterfaceMap == null) {
+ return services;
+ }
+ appInterfaceMap.values().forEach(serviceUrlMap ->
+ serviceUrlMap.forEach((service, urls) -> {
+ if (CollectionUtils.isNotEmpty(urls)) {
+ services.add(service);
+ }
+ }));
+ return services;
+ }
+
+ public Set<String> findApplications() {
+ ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+ if (appInterfaceMap == null) {
+ return Sets.newHashSet();
+ }
+ return Sets.newHashSet(appInterfaceMap.keySet());
+ }
+
+ public List<Provider> findByService(String serviceName) {
+ ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+ if (appInterfaceMap == null) {
+ return Lists.newArrayList();
+ }
+ List<InstanceAddressURL> providerUrls = Lists.newArrayList();
+ appInterfaceMap.values().forEach(serviceUrlMap ->
+ serviceUrlMap.forEach((service, urls) -> {
+ if (CollectionUtils.isNotEmpty(urls) && service.equals(serviceName)) {
+ providerUrls.addAll(urls);
+ }
+ }));
+ return urlsToProviderList(providerUrls).stream()
+ .filter(provider -> provider.getService().equals(serviceName))
+ .collect(Collectors.toList());
+ }
+
+ public List<Provider> findByAddress(String providerAddress) {
+ ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+ if (appInterfaceMap == null) {
+ return Lists.newArrayList();
+ }
+ List<InstanceAddressURL> providerUrls = Lists.newArrayList();
+ appInterfaceMap.values().forEach(serviceUrlMap ->
+ serviceUrlMap.forEach((service, urls) -> {
+ if (CollectionUtils.isNotEmpty(urls)) {
+ urls.forEach(url -> {
+ if ((url.getInstance().getHost().equals(providerAddress))) {
+ providerUrls.add(url);
+ }
+ });
+ }
+ }));
+ return urlsToProviderList(providerUrls);
+ }
+
+ public List<Provider> findByApplication(String application) {
+ ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+ if (appInterfaceMap == null || appInterfaceMap.get(application) == null) {
+ return Lists.newArrayList();
+ }
+ List<InstanceAddressURL> providerUrls = Lists.newArrayList();
+ appInterfaceMap.get(application).forEach((service, urls) -> providerUrls.addAll(urls));
+ return urlsToProviderList(providerUrls);
+ }
+
+ public String findVersionInApplication(String application) {
+ ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+ if (appInterfaceMap == null || appInterfaceMap.get(application) == null) {
+ return null;
+ }
+ Map<String, List<InstanceAddressURL>> urlsMap = appInterfaceMap.get(application);
+ for (Map.Entry<String, List<InstanceAddressURL>> entry : urlsMap.entrySet()) {
+ List<InstanceAddressURL> urls = entry.getValue();
+ if (CollectionUtils.isNotEmpty(urls)) {
+ return urls.get(0).getParameter(Constants.SPECIFICATION_VERSION_KEY, "3.0.0");
+ }
+ }
+ return null;
+ }
+
+ private List<Provider> urlsToProviderList(List<InstanceAddressURL> urls) {
+ List<Provider> providers = Lists.newArrayList();
+ urls.stream().distinct().forEach(url -> {
+ ServiceInstance instance = url.getInstance();
+ MetadataInfo metadataInfo = url.getMetadataInfo();
+
+ metadataInfo.getServices().forEach((serviceKey, serviceInfo) -> {
+ Provider p = new Provider();
+ String service = serviceInfo.getServiceKey();
+ p.setService(service);
+ p.setAddress(url.getAddress());
+ p.setApplication(instance.getServiceName());
+ p.setUrl(url.toParameterString());
+ p.setDynamic(url.getParameter("dynamic", true));
+ p.setEnabled(url.getParameter(Constants.ENABLED_KEY, true));
+ p.setWeight(url.getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT));
+ p.setUsername(url.getParameter("owner"));
+ p.setRegistrySource(RegistrySource.INSTANCE);
+ providers.add(p);
+ });
+ });
+ return providers;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InterfaceRegistryCache.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InterfaceRegistryCache.java
new file mode 100644
index 0000000..ab5b3be
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InterfaceRegistryCache.java
@@ -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.admin.service.impl;
+
+import org.apache.dubbo.admin.service.RegistryCache;
+import org.apache.dubbo.common.URL;
+
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * interface registry url cache
+ * key --> category,value --> ConcurrentMap<serviceKey, Map<hash, URL>>
+ */
+@Component
+public class InterfaceRegistryCache implements RegistryCache<String, ConcurrentMap<String, Map<String, URL>>> {
+
+ private final ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> registryCache = new ConcurrentHashMap<>();
+
+ @Override
+ public void put(String key, ConcurrentMap<String, Map<String, URL>> value) {
+ registryCache.put(key, value);
+ }
+
+ @Override
+ public ConcurrentMap<String, Map<String, URL>> get(String key) {
+ return registryCache.get(key);
+ }
+
+ public ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> getRegistryCache() {
+ return registryCache;
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java
new file mode 100644
index 0000000..b234eaf
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java
@@ -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.admin.service.impl;
+
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
+import org.apache.dubbo.admin.common.util.YamlParser;
+import org.apache.dubbo.admin.model.dto.MeshRouteDTO;
+import org.apache.dubbo.admin.model.store.mesh.destination.DestinationRule;
+import org.apache.dubbo.admin.model.store.mesh.virtualservice.VirtualServiceRule;
+import org.apache.dubbo.admin.service.MeshRouteService;
+
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+
+@Service
+public class MeshRouteServiceImpl extends AbstractService implements MeshRouteService {
+
+ @Override
+ public boolean createMeshRule(MeshRouteDTO meshRoute) {
+ String routeRule = meshRoute.getMeshRule();
+ checkMeshRule(routeRule);
+ String id = ConvertUtil.getIdFromDTO(meshRoute);
+ String path = getPath(id);
+ dynamicConfiguration.setConfig(path, routeRule);
+ return true;
+ }
+
+ @Override
+ public boolean updateMeshRule(MeshRouteDTO meshRoute) {
+ String id = ConvertUtil.getIdFromDTO(meshRoute);
+ String path = getPath(id);
+ checkMeshRule(meshRoute.getMeshRule());
+ dynamicConfiguration.setConfig(path, meshRoute.getMeshRule());
+ return true;
+ }
+
+ private void checkMeshRule(String meshRule) {
+ Iterable<Object> objectIterable = YamlParser.loadAll(meshRule);
+ for (Object result : objectIterable) {
+ Map resultMap = (Map) result;
+ if ("DestinationRule".equals(resultMap.get("kind"))) {
+ YamlParser.loadObject(YamlParser.dumpObject(result), DestinationRule.class);
+ } else if ("VirtualService".equals(resultMap.get("kind"))) {
+ YamlParser.loadObject(YamlParser.dumpObject(result), VirtualServiceRule.class);
+ }
+ }
+ }
+
+ @Override
+ public boolean deleteMeshRule(String id) {
+ String path = getPath(id);
+ return dynamicConfiguration.deleteConfig(path);
+ }
+
+ @Override
+ public MeshRouteDTO findMeshRoute(String id) {
+ String path = getPath(id);
+ String rule = dynamicConfiguration.getConfig(path);
+ if (rule == null) {
+ return null;
+ }
+ MeshRouteDTO meshRoute = new MeshRouteDTO();
+ meshRoute.setApplication(id);
+ meshRoute.setMeshRule(rule);
+ return meshRoute;
+ }
+
+ private String getPath(String id) {
+ return Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + id + Constants.MESH_RULE_SUFFIX;
+ }
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
index 0d83081..1defce7 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
@@ -18,16 +18,14 @@
import org.apache.dubbo.admin.common.exception.ParamValidationException;
import org.apache.dubbo.admin.common.util.Constants;
-import org.apache.dubbo.admin.common.util.Pair;
-import org.apache.dubbo.admin.common.util.ParseUtils;
import org.apache.dubbo.admin.common.util.SyncUtils;
import org.apache.dubbo.admin.common.util.Tool;
import org.apache.dubbo.admin.model.domain.Provider;
import org.apache.dubbo.admin.model.dto.ServiceDTO;
-import org.apache.dubbo.admin.service.OverrideService;
import org.apache.dubbo.admin.service.ProviderService;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -37,7 +35,6 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentMap;
@@ -49,7 +46,7 @@
public class ProviderServiceImpl extends AbstractService implements ProviderService {
@Autowired
- OverrideService overrideService;
+ private InstanceRegistryQueryHelper instanceRegistryQueryHelper;
@Override
public void create(Provider provider) {
@@ -63,57 +60,27 @@
return metaDataCollector.getProviderMetaData(providerIdentifier);
}
-
- @Override
- public void deleteStaticProvider(String id) {
- URL oldProvider = findProviderUrl(id);
- if (oldProvider == null) {
- throw new IllegalStateException("Provider was changed!");
- }
- registry.unregister(oldProvider);
- }
-
- @Override
- public void updateProvider(Provider provider) {
- String hash = provider.getHash();
- if (hash == null) {
- throw new IllegalStateException("no provider id");
- }
-
- URL oldProvider = findProviderUrl(hash);
- if (oldProvider == null) {
- throw new IllegalStateException("Provider was changed!");
- }
- URL newProvider = provider.toUrl();
-
- registry.unregister(oldProvider);
- registry.register(newProvider);
- }
-
- @Override
- public Provider findProvider(String id) {
- return SyncUtils.url2Provider(findProviderUrlPair(id));
- }
-
- public Pair<String, URL> findProviderUrlPair(String id) {
- return SyncUtils.filterFromCategory(getRegistryCache(), Constants.PROVIDERS_CATEGORY, id);
- }
-
@Override
public Set<String> findServices() {
Set<String> ret = new HashSet<>();
- ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
- if (providerUrls != null){
+ ConcurrentMap<String, Map<String, URL>> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+ if (providerUrls != null) {
ret.addAll(providerUrls.keySet());
}
+ ret.addAll(instanceRegistryQueryHelper.findServices());
return ret;
}
@Override
+ public Set<String> findInstanceApplications() {
+ return instanceRegistryQueryHelper.findApplications();
+ }
+
+ @Override
public List<String> findAddresses() {
List<String> ret = new ArrayList<String>();
- ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+ ConcurrentMap<String, Map<String, URL>> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY);
if (null == providerUrls) {
return ret;
}
@@ -128,80 +95,15 @@
}
}
}
-
- return ret;
- }
-
- @Override
- public List<String> findAddressesByApplication(String application) {
- List<String> ret = new ArrayList<String>();
- ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
- for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
- Map<String, URL> value = e1.getValue();
- for (Map.Entry<String, URL> e2 : value.entrySet()) {
- URL u = e2.getValue();
- if (application.equals(u.getParameter(Constants.APPLICATION))) {
- String addr = u.getAddress();
- if (addr != null) {
- ret.add(addr);
- }
- }
- }
- }
-
- return ret;
- }
-
- @Override
- public List<String> findAddressesByService(String service) {
- List<String> ret = new ArrayList<String>();
- ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
- if (null == providerUrls) {
- return ret;
- }
-
- for (Map.Entry<String, URL> e2 : providerUrls.get(service).entrySet()) {
- URL u = e2.getValue();
- String app = u.getAddress();
- if (app != null) {
- ret.add(app);
- }
- }
-
- return ret;
- }
-
- @Override
- public List<String> findApplicationsByServiceName(String service) {
- List<String> ret = new ArrayList<String>();
- ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
- if (null == providerUrls) {
- return ret;
- }
-
- Map<String, URL> value = providerUrls.get(service);
- if (value == null) {
- return ret;
- }
- for (Map.Entry<String, URL> e2 : value.entrySet()) {
- URL u = e2.getValue();
- String app = u.getParameter(Constants.APPLICATION);
- if (app != null){
- ret.add(app);
- }
- }
-
return ret;
}
@Override
public List<Provider> findByService(String serviceName) {
- return SyncUtils.url2ProviderList(findProviderUrlByService(serviceName));
- }
-
- @Override
- public List<Provider> findByAppandService(String app, String serviceName) {
- return SyncUtils.url2ProviderList(findProviderUrlByAppandService(app, serviceName));
+ List<Provider> instanceProviders = instanceRegistryQueryHelper.findByService(serviceName);
+ List<Provider> interfaceProviders = SyncUtils.url2ProviderList(findProviderUrlByService(serviceName));
+ instanceProviders.addAll(interfaceProviders);
+ return instanceProviders;
}
private Map<String, URL> findProviderUrlByService(String service) {
@@ -209,7 +111,7 @@
filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
- return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+ return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
}
@Override
@@ -220,12 +122,15 @@
private Map<String, URL> findAllProviderUrl() {
Map<String, String> filter = new HashMap<String, String>();
filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
- return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+ return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
}
@Override
public List<Provider> findByAddress(String providerAddress) {
- return SyncUtils.url2ProviderList(findProviderUrlByAddress(providerAddress));
+ List<Provider> instanceProviders = instanceRegistryQueryHelper.findByAddress(providerAddress);
+ List<Provider> interfaceProviders = SyncUtils.url2ProviderList(findProviderUrlByAddress(providerAddress));
+ instanceProviders.addAll(interfaceProviders);
+ return instanceProviders;
}
public Map<String, URL> findProviderUrlByAddress(String address) {
@@ -233,37 +138,14 @@
filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
- return SyncUtils.filterFromCategory(getRegistryCache(), filter);
- }
-
- @Override
- public List<String> findServicesByAddress(String address) {
- List<String> ret = new ArrayList<String>();
-
- ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
- if (providerUrls == null || address == null || address.length() == 0) {
- return ret;
- }
-
- for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
- Map<String, URL> value = e1.getValue();
- for (Map.Entry<String, URL> e2 : value.entrySet()) {
- URL u = e2.getValue();
- if (address.equals(u.getAddress())) {
- ret.add(e1.getKey());
- break;
- }
- }
- }
-
- return ret;
+ return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
}
@Override
public Set<String> findApplications() {
- Set<String> ret = new HashSet<>();
- ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
- if (providerUrls == null){
+ Set<String> ret = instanceRegistryQueryHelper.findApplications();
+ ConcurrentMap<String, Map<String, URL>> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+ if (providerUrls == null) {
return ret;
}
@@ -283,11 +165,18 @@
@Override
public List<Provider> findByApplication(String application) {
- return SyncUtils.url2ProviderList(findProviderUrlByApplication(application));
+ List<Provider> instanceProviders = instanceRegistryQueryHelper.findByApplication(application);
+ List<Provider> interfaceProviders = SyncUtils.url2ProviderList(findProviderUrlByApplication(application));
+ instanceProviders.addAll(interfaceProviders);
+ return instanceProviders;
}
@Override
public String findVersionInApplication(String application) {
+ String version = instanceRegistryQueryHelper.findVersionInApplication(application);
+ if (StringUtils.isNotBlank(version)){
+ return version;
+ }
List<String> services = findServicesByApplication(application);
if (services == null || services.size() == 0) {
throw new ParamValidationException("there is no service for application: " + application);
@@ -313,23 +202,22 @@
filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
filter.put(Constants.APPLICATION, app);
filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
- return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+ return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
}
-
private Map<String, URL> findProviderUrlByApplication(String application) {
Map<String, String> filter = new HashMap<>();
filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
filter.put(Constants.APPLICATION, application);
- return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+ return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
}
@Override
public List<String> findServicesByApplication(String application) {
List<String> ret = new ArrayList<String>();
- ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+ ConcurrentMap<String, Map<String, URL>> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY);
if (providerUrls == null || application == null || application.length() == 0) {
return ret;
}
@@ -349,59 +237,6 @@
}
@Override
- public List<String> findMethodsByService(String service) {
- List<String> ret = new ArrayList<String>();
-
- ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
- if (providerUrls == null || service == null || service.length() == 0){
- return ret;
- }
-
- Map<String, URL> providers = providerUrls.get(service);
- if (null == providers || providers.isEmpty()) {
- return ret;
- }
-
- Entry<String, URL> p = providers.entrySet().iterator().next();
- String value = p.getValue().getParameter("methods");
- if (value == null || value.length() == 0) {
- return ret;
- }
- String[] methods = value.split(ParseUtils.METHOD_SPLIT);
- if (methods == null || methods.length == 0) {
- return ret;
- }
-
- for (String m : methods) {
- ret.add(m);
- }
- return ret;
- }
-
- private URL findProviderUrl(String id) {
- return findProvider(id).toUrl();
- }
-
- @Override
- public Provider findByServiceAndAddress(String service, String address) {
- return SyncUtils.url2Provider(findProviderUrl(service, address));
- }
-
- private Pair<String, URL> findProviderUrl(String service, String address) {
- Map<String, String> filter = new HashMap<String, String>();
- filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
- filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
-
- Map<String, URL> ret = SyncUtils.filterFromCategory(getRegistryCache(), filter);
- if (ret.isEmpty()) {
- return null;
- } else {
- String key = ret.entrySet().iterator().next().getKey();
- return new Pair<String, URL>(key, ret.get(key));
- }
- }
-
- @Override
public Set<ServiceDTO> getServiceDTOS(String pattern, String filter, String env) {
List<Provider> providers = new ArrayList<>();
if (!filter.contains(Constants.ANY_VALUE) && !filter.contains(Constants.INTERROGATION_POINT)) {
@@ -420,15 +255,14 @@
candidates = findServices();
} else if (Constants.APPLICATION.equals(pattern)) {
candidates = findApplications();
- }
- else if (Constants.IP.equals(pattern)) {
+ } else if (Constants.IP.equals(pattern)) {
candidates = findAddresses().stream().collect(Collectors.toSet());
}
// replace dot symbol and asterisk symbol to java-based regex pattern
filter = filter.toLowerCase().replace(Constants.PUNCTUATION_POINT, Constants.PUNCTUATION_SEPARATOR_POINT);
// filter start with [* 、? 、+] will triggering PatternSyntaxException
if (filter.startsWith(Constants.ANY_VALUE)
- || filter.startsWith(Constants.INTERROGATION_POINT) || filter.startsWith(Constants.PLUS_SIGNS)) {
+ || filter.startsWith(Constants.INTERROGATION_POINT) || filter.startsWith(Constants.PLUS_SIGNS)) {
filter = Constants.PUNCTUATION_POINT + filter;
}
// search with no case insensitive
@@ -438,19 +272,16 @@
if (matcher.matches() || matcher.lookingAt()) {
if (Constants.SERVICE.equals(pattern)) {
providers.addAll(findByService(candidate));
- }
- else if (Constants.IP.equals(pattern)) {
+ } else if (Constants.IP.equals(pattern)) {
providers.addAll(findByAddress(candidate));
- }
- else {
+ } else {
providers.addAll(findByApplication(candidate));
}
}
}
}
- Set<ServiceDTO> result = convertProviders2DTO(providers);
- return result;
+ return convertProviders2DTO(providers);
}
/**
@@ -472,6 +303,7 @@
s.setService(interfaze);
s.setGroup(group);
s.setVersion(version);
+ s.setRegistrySource(provider.getRegistrySource());
result.add(s);
}
return result;
diff --git a/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.mapping.ServiceMapping b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.mapping.ServiceMapping
new file mode 100644
index 0000000..83709e7
--- /dev/null
+++ b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.mapping.ServiceMapping
@@ -0,0 +1 @@
+zookeeper=org.apache.dubbo.admin.registry.mapping.impl.ZookeeperServiceMapping
\ No newline at end of file
diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
index 9448a93..0626da2 100644
--- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
+++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
@@ -73,7 +73,7 @@
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext,
"admin.registry.address=zookeeper://" + zkServer.getConnectString());
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext,
- "admin.metadata.address=zookeeper://" + zkServer.getConnectString());
+ "admin.metadata-report.address=zookeeper://" + zkServer.getConnectString());
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext,
"admin.config-center=zookeeper://" + zkServer.getConnectString());
}
diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java
new file mode 100644
index 0000000..8cfdd9f
--- /dev/null
+++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.admin.controller;
+
+import org.apache.dubbo.admin.AbstractSpringIntegrationTest;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.model.dto.MeshRouteDTO;
+import org.apache.dubbo.admin.service.ProviderService;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.After;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+
+public class MeshRouteControllerTest extends AbstractSpringIntegrationTest {
+
+ private final String env = "whatever";
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @MockBean
+ private ProviderService providerService;
+
+ @After
+ public void tearDown() throws Exception {
+ if (zkClient.checkExists().forPath("/dubbo") != null) {
+ zkClient.delete().deletingChildrenIfNeeded().forPath("/dubbo");
+ }
+ }
+
+ private String getFileContent(String file) throws IOException {
+ try (InputStream stream = this.getClass().getResourceAsStream(file)) {
+ byte[] bytes = new byte[stream.available()];
+ stream.read(bytes);
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+ }
+
+
+ @Test
+ public void createMeshRoute() throws IOException {
+ MeshRouteDTO meshRoute = new MeshRouteDTO();
+ ResponseEntity<String> response;
+ String application = "mesh-create";
+ // application are all blank
+ response = restTemplate.postForEntity(url("/api/{env}/rules/route/mesh"), meshRoute, String.class, env);
+ assertFalse("should return a fail response, when application is blank", (Boolean) objectMapper.readValue(response.getBody(), Map.class).get("success"));
+
+ // valid mesh rule
+ meshRoute.setApplication(application);
+ meshRoute.setMeshRule(getFileContent("/MeshRoute.yml"));
+ when(providerService.findVersionInApplication(application)).thenReturn("3.0.0");
+ response = restTemplate.postForEntity(url("/api/{env}/rules/route/mesh"), meshRoute, String.class, env);
+ assertEquals(HttpStatus.CREATED, response.getStatusCode());
+ assertTrue(Boolean.valueOf(response.getBody()));
+ }
+
+
+ @Test
+ public void detailMeshRoute() throws Exception {
+ String id = "1";
+ ResponseEntity<String> response;
+ // when balancing is not exist
+ response = restTemplate.getForEntity(url("/api/{env}/rules/route/mesh/{id}"), String.class, env, id);
+ assertFalse("should return a fail response, when id is null", (Boolean) objectMapper.readValue(response.getBody(), Map.class).get("success"));
+ // when balancing is not null
+ String application = "mesh-detail";
+ String content = getFileContent("/MeshRoute.yml");
+ String path = "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + application + Constants.MESH_RULE_SUFFIX;
+ zkClient.create().creatingParentContainersIfNeeded().forPath(path);
+ zkClient.setData().forPath(path, content.getBytes());
+ assertNotNull("zk path should not be null before deleting", zkClient.checkExists().forPath(path));
+
+ response = restTemplate.getForEntity(url("/api/{env}/rules/route/mesh/{id}"), String.class, env, application);
+ assertEquals(HttpStatus.OK, response.getStatusCode());
+ assertEquals(content, objectMapper.readValue(response.getBody(), Map.class).get("meshRule"));
+ }
+
+ @Test
+ public void updateMeshRoute() throws Exception {
+ String application = "mesh-update";
+ String content = getFileContent("/MeshRoute.yml");
+ String path = "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + application + Constants.MESH_RULE_SUFFIX;
+ zkClient.create().creatingParentContainersIfNeeded().forPath(path);
+ zkClient.setData().forPath(path, content.getBytes());
+ assertNotNull("zk path should not be null before deleting", zkClient.checkExists().forPath(path));
+
+ MeshRouteDTO meshRoute = new MeshRouteDTO();
+ meshRoute.setApplication(application);
+ meshRoute.setMeshRule(getFileContent("/MeshRouteTest2.yml"));
+
+ ResponseEntity<String> response = restTemplate.exchange(url("/api/{env}/rules/route/mesh/{id}"), HttpMethod.PUT, new HttpEntity<>(meshRoute, null), String.class, env, application);
+ assertEquals(HttpStatus.OK, response.getStatusCode());
+ assertTrue(Boolean.valueOf(response.getBody()));
+ byte[] bytes = zkClient.getData().forPath(path);
+ String updatedConfig = new String(bytes);
+ assertEquals(updatedConfig, meshRoute.getMeshRule());
+ }
+
+
+ @Test
+ public void deleteMeshRoute() throws Exception {
+ String application = "mesh-delete";
+ String content = getFileContent("/MeshRoute.yml");
+ String path = "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + application + Constants.MESH_RULE_SUFFIX;
+ zkClient.create().creatingParentContainersIfNeeded().forPath(path);
+ zkClient.setData().forPath(path, content.getBytes());
+ assertNotNull("zk path should not be null before deleting", zkClient.checkExists().forPath(path));
+
+ ResponseEntity<String> response = restTemplate.exchange(url("/api/{env}/rules/route/mesh/{id}"), HttpMethod.DELETE, new HttpEntity<>(null), String.class, env, application);
+ assertEquals(HttpStatus.OK, response.getStatusCode());
+ assertNull(zkClient.checkExists().forPath(path));
+ }
+}
diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/service/RegistryServerSyncTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/service/RegistryServerSyncTest.java
index a8ecc7c..1be485d 100644
--- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/service/RegistryServerSyncTest.java
+++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/service/RegistryServerSyncTest.java
@@ -18,16 +18,22 @@
package org.apache.dubbo.admin.service;
import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.service.impl.InterfaceRegistryCache;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.url.component.URLParam;
import org.apache.dubbo.registry.Registry;
+
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.util.ReflectionTestUtils;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
@@ -46,9 +52,11 @@
@InjectMocks
private RegistryServerSync registryServerSync;
- @Test
- public void testGetRegistryCache() {
- registryServerSync.getRegistryCache();
+ private InterfaceRegistryCache interfaceRegistryCache = new InterfaceRegistryCache();
+
+ @Before
+ public void setUp() throws Exception {
+ ReflectionTestUtils.setField(registryServerSync, "interfaceRegistryCache", interfaceRegistryCache);
}
@Test
@@ -71,27 +79,32 @@
// when url.getProtocol is not empty protocol
URL consumerUrl = mock(URL.class);
URL providerUrl = mock(URL.class);
-
- when(consumerUrl.getParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY)).thenReturn(Constants.CONSUMER_PROTOCOL);
+ HashMap<String, String> consumerUrlParam = new HashMap<>();
+ consumerUrlParam.put(Constants.CATEGORY_KEY,Constants.CONSUMER_PROTOCOL);
+ HashMap<String, String> providerUrlParam = new HashMap<>();
+ providerUrlParam.put(Constants.CATEGORY_KEY,Constants.PROVIDER_PROTOCOL);
+ when(consumerUrl.getUrlParam()).thenReturn(URLParam.parse(consumerUrlParam));
when(consumerUrl.getServiceInterface()).thenReturn("org.apache.dubbo.consumer");
- when(consumerUrl.getServiceKey()).thenReturn("org.apache.dubbo.consumer");
when(consumerUrl.toFullString()).thenReturn("consumer://192.168.1.10/sunbufu.dubbo.consumer?application=dubbo&category=consumer&check=false&dubbo=2.7.0&interface=sunbufu.dubbo.consumer&loadbalabce=roundrobin&mehods=sayHi,sayGoodBye&owner=sunbufu&pid=18&protocol=dubbo&side=consumer&timeout=3000×tamp=1548127407769");
+ when(providerUrl.getUrlParam()).thenReturn(URLParam.parse(providerUrlParam));
when(providerUrl.getParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY)).thenReturn(Constants.PROVIDER_PROTOCOL);
when(providerUrl.getServiceInterface()).thenReturn("org.apache.dubbo.provider");
- when(providerUrl.getServiceKey()).thenReturn("org.apache.dubbo.provider");
when(providerUrl.toFullString()).thenReturn("consumer://192.168.1.10/sunbufu.dubbo.consumer?application=dubbo&category=consumer&check=false&dubbo=2.6.2&interface=sunbufu.dubbo.consumer&loadbalabce=roundrobin&mehods=sayHi,sayGoodBye&owner=sunbufu&pid=18&protocol=dubbo&side=consumer&timeout=3000×tamp=1548127407769");
registryServerSync.notify(Arrays.asList(consumerUrl, consumerUrl, providerUrl));
- ConcurrentMap<String, Map<String, URL>> consumerMap = registryServerSync.getRegistryCache().get(Constants.CONSUMER_PROTOCOL);
+ ConcurrentMap<String, Map<String, URL>> consumerMap = interfaceRegistryCache.get(Constants.CONSUMER_PROTOCOL);
assertTrue(consumerMap.keySet().contains("org.apache.dubbo.consumer"));
- ConcurrentMap<String, Map<String, URL>> providerMap = registryServerSync.getRegistryCache().get(Constants.PROVIDER_PROTOCOL);
+ ConcurrentMap<String, Map<String, URL>> providerMap = interfaceRegistryCache.get(Constants.PROVIDER_PROTOCOL);
assertTrue(providerMap.keySet().contains("org.apache.dubbo.provider"));
// when url.getProtocol is empty protocol
when(consumerUrl.getProtocol()).thenReturn(Constants.EMPTY_PROTOCOL);
- when(consumerUrl.getParameter(Constants.GROUP_KEY)).thenReturn("dubbo");
- when(consumerUrl.getParameter(Constants.VERSION_KEY)).thenReturn("2.7.0");
+ consumerUrlParam = new HashMap<>();
+ consumerUrlParam.put(Constants.CATEGORY_KEY,Constants.CONSUMER_PROTOCOL);
+ consumerUrlParam.put(Constants.GROUP_KEY,"dubbo");
+ consumerUrlParam.put(Constants.VERSION_KEY,"2.7.0");
+ when(consumerUrl.getUrlParam()).thenReturn(URLParam.parse(consumerUrlParam));
registryServerSync.notify(Collections.singletonList(consumerUrl));
assertTrue(!consumerMap.keySet().contains("org.apache.dubbo.consumer"));
diff --git a/dubbo-admin-server/src/test/resources/MeshRoute.yml b/dubbo-admin-server/src/test/resources/MeshRoute.yml
new file mode 100644
index 0000000..b6a1071
--- /dev/null
+++ b/dubbo-admin-server/src/test/resources/MeshRoute.yml
@@ -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]
\ No newline at end of file
diff --git a/dubbo-admin-server/src/test/resources/MeshRouteTest2.yml b/dubbo-admin-server/src/test/resources/MeshRouteTest2.yml
new file mode 100644
index 0000000..4d3454b
--- /dev/null
+++ b/dubbo-admin-server/src/test/resources/MeshRouteTest2.yml
@@ -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]
diff --git a/dubbo-admin-ui/src/api/menu.js b/dubbo-admin-ui/src/api/menu.js
index 0a4fced..a68f536 100644
--- a/dubbo-admin-ui/src/api/menu.js
+++ b/dubbo-admin-ui/src/api/menu.js
@@ -23,7 +23,8 @@
group: 'governance',
items: [
{ title: 'routingRule', path: '/governance/routingRule' },
- { title: 'tagRule', path: '/governance/tagRule', badge: 'new' },
+ { title: 'tagRule', path: '/governance/tagRule' },
+ { title: 'meshRule', path: '/governance/meshRule', badge: 'new' },
{ title: 'accessControl', path: '/governance/access' },
{ title: 'dynamicConfig', path: '/governance/config' },
{ title: 'weightAdjust', path: '/governance/weight' },
diff --git a/dubbo-admin-ui/src/components/ServiceDetail.vue b/dubbo-admin-ui/src/components/ServiceDetail.vue
index 366b5ff..79fa779 100644
--- a/dubbo-admin-ui/src/components/ServiceDetail.vue
+++ b/dubbo-admin-ui/src/components/ServiceDetail.vue
@@ -54,6 +54,7 @@
<template slot="items" slot-scope="props">
<td>{{getIp(props.item.address)}}</td>
<td>{{getPort(props.item.address)}}</td>
+ <td>{{props.item.registrySource}}</td>
<td></td>
<td></td>
<td>{{props.item.weight}}</td>
@@ -167,6 +168,10 @@
value: 'port'
},
{
+ text: this.$t('registrySource'),
+ value: 'registrySource'
+ },
+ {
text: this.$t('timeout'),
value: 'timeout'
},
@@ -204,7 +209,16 @@
this.$axios.get('/service/' + service)
.then(response => {
this.providerDetails = response.data.providers
+ const instanceRegistry = this.$t('instanceRegistry')
+ const interfaceRegistry = this.$t('interfaceRegistry')
for (let i = 0; i < this.providerDetails.length; i++) {
+ if (this.providerDetails[i].registrySource === 'INSTANCE') {
+ this.providerDetails[i].registrySource = instanceRegistry
+ }
+ if (this.providerDetails[i].registrySource === 'INTERFACE') {
+ this.providerDetails[i].registrySource = interfaceRegistry
+ }
+ console.log(this.providerDetails[i])
this.$set(this.providerDetails[i], 'hint', 'url')
}
this.consumerDetails = response.data.consumers
diff --git a/dubbo-admin-ui/src/components/ServiceSearch.vue b/dubbo-admin-ui/src/components/ServiceSearch.vue
index c7fa2c8..c5ce4fb 100644
--- a/dubbo-admin-ui/src/components/ServiceSearch.vue
+++ b/dubbo-admin-ui/src/components/ServiceSearch.vue
@@ -81,11 +81,12 @@
<td>{{props.item.group}}</td>
<td>{{props.item.version}}</td>
<td>{{props.item.appName}}</td>
+ <td>{{props.item.registrySource}}</td>
<td class="text-xs-center px-0" nowrap>
<v-btn
class="tiny"
color='success'
- :href='getHref(props.item.service, props.item.appName, props.item.group, props.item.version)'
+ :href='getHref(props.item.service, props.item.appName, props.item.group, props.item.version,props.item.registrySource)'
>
{{ $t('detail') }}
</v-btn>
@@ -112,7 +113,7 @@
<v-list-tile
v-for="(item, i) in options"
:key="i"
- :href='governanceHref(item.value, props.item.service, props.item.appName, props.item.group, props.item.version)'
+ :href='governanceHref(item.value, props.item.service, props.item.appName, props.item.group, props.item.version,props.item.registrySource)'
>
<v-list-tile-title class="small-list">{{ $t(item.title) }}</v-list-tile-title>
</v-list-tile>
@@ -198,7 +199,17 @@
if (!this.resultPage || !this.resultPage.content) {
return []
}
- return this.resultPage.content
+ const instanceRegistry = this.$t('instanceRegistry')
+ const interfaceRegistry = this.$t('interfaceRegistry')
+ return this.resultPage.content.filter(function (item) {
+ if (item.registrySource === 'INSTANCE') {
+ item.registrySource = instanceRegistry
+ }
+ if (item.registrySource === 'INTERFACE') {
+ item.registrySource = interfaceRegistry
+ }
+ return item
+ })
}
},
watch: {
@@ -244,6 +255,11 @@
align: 'left'
},
{
+ text: this.$t('registrySource'),
+ value: 'registry',
+ align: 'left'
+ },
+ {
text: this.$t('operation'),
value: 'operation',
sortable: false,
diff --git a/dubbo-admin-ui/src/components/governance/MeshRule.vue b/dubbo-admin-ui/src/components/governance/MeshRule.vue
new file mode 100644
index 0000000..d55fd5b
--- /dev/null
+++ b/dubbo-admin-ui/src/components/governance/MeshRule.vue
@@ -0,0 +1,422 @@
+<!--
+ - 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.
+ -->
+
+<template>
+ <v-container grid-list-xl fluid>
+ <v-layout row wrap>
+ <v-flex lg12>
+ <breadcrumb title="meshRule" :items="breads"></breadcrumb>
+ </v-flex>
+ </v-layout>
+ <v-flex lg12>
+ <v-card flat color="transparent">
+ <v-card-text>
+ <v-form>
+ <v-layout row wrap>
+ <v-combobox
+ id="serviceSearch"
+ :loading="searchLoading"
+ :items="typeAhead"
+ :search-input.sync="input"
+ @keyup.enter="submit"
+ v-model="filter"
+ flat
+ append-icon=""
+ hide-no-data
+ :label="$t('searchMeshRule')"
+ ></v-combobox>
+ <v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn>
+
+ </v-layout>
+ </v-form>
+ </v-card-text>
+ </v-card>
+ </v-flex>
+ <v-flex lg12>
+ <v-card>
+ <v-toolbar flat color="transparent" class="elevation-0">
+ <v-toolbar-title><span class="headline">{{$t('searchResult')}}</span></v-toolbar-title>
+ <v-spacer></v-spacer>
+ <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">{{$t('create')}}</v-btn>
+ </v-toolbar>
+
+ <v-card-text class="pa-0">
+ <v-data-table
+ :headers="headers"
+ :items="meshRoutingRules"
+ hide-actions
+ class="elevation-0"
+ >
+ <template slot="items" slot-scope="props">
+ <td class="text-xs-left">{{ props.item.application }}</td>
+ <td class="text-xs-center px-0">
+ <v-tooltip bottom>
+ <v-icon small
+ class="mr-2"
+ color="blue"
+ slot="activator"
+ @click="itemOperation('visibility', props.item)">visibility
+ </v-icon>
+ <span>{{$t('view')}}</span>
+ </v-tooltip>
+ <v-tooltip bottom>
+ <v-icon small
+ class="mr-2"
+ color="blue"
+ slot="activator"
+ @click="itemOperation('edit', props.item)">edit
+ </v-icon>
+ <span>Edit</span>
+ </v-tooltip>
+ <v-tooltip bottom>
+ <v-icon small
+ class="mr-2"
+ slot="activator"
+ color="red"
+ @click="itemOperation('delete', props.item)">delete
+ </v-icon>
+ <span>Delete</span>
+ </v-tooltip>
+ </td>
+ </template>
+ </v-data-table>
+ </v-card-text>
+ </v-card>
+ </v-flex>
+
+ <v-dialog v-model="dialog" width="800px" persistent>
+ <v-card>
+ <v-card-title class="justify-center">
+ <span class="headline">{{$t('createNewMeshRule')}}</span>
+ </v-card-title>
+ <v-card-text>
+ <v-text-field
+ :label="$t('appName')"
+ :hint="$t('appNameHint')"
+ v-model="application"
+ ></v-text-field>
+
+ <v-subheader class="pa-0 mt-3">{{$t('ruleContent')}}</v-subheader>
+ <ace-editor v-model="ruleText" :readonly="readonly"></ace-editor>
+
+ </v-card-text>
+ <v-card-actions>
+ <v-spacer></v-spacer>
+ <v-btn flat @click.native="closeDialog">{{$t('close')}}</v-btn>
+ <v-btn depressed color="primary" @click.native="saveItem">{{$t('save')}}</v-btn>
+ </v-card-actions>
+ </v-card>
+ </v-dialog>
+
+ <v-dialog v-model="warn.display" persistent max-width="500px">
+ <v-card>
+ <v-card-title class="headline">{{$t(this.warn.title)}}</v-card-title>
+ <v-card-text>{{this.warn.text}}</v-card-text>
+ <v-card-actions>
+ <v-spacer></v-spacer>
+ <v-btn flat @click.native="closeWarn">CANCLE</v-btn>
+ <v-btn depressed color="primary" @click.native="deleteItem(warn.status)">{{$t('confirm')}}</v-btn>
+ </v-card-actions>
+ </v-card>
+ </v-dialog>
+
+ </v-container>
+
+</template>
+<script>
+ import yaml from 'js-yaml'
+ import AceEditor from '@/components/public/AceEditor'
+ import operations from '@/api/operation'
+ import Search from '@/components/public/Search'
+ import Breadcrumb from '@/components/public/Breadcrumb'
+
+ export default {
+ components: {
+ AceEditor,
+ Search,
+ Breadcrumb
+ },
+ data: () => ({
+ dropdown_font: ['Service', 'App', 'IP'],
+ ruleKeys: ['enabled', 'force', 'dynamic', 'runtime', 'group', 'version', 'rule'],
+ pattern: 'Service',
+ filter: '',
+ dialog: false,
+ updateId: '',
+ application: '',
+ searchLoading: false,
+ typeAhead: [],
+ input: null,
+ timerID: null,
+ warn: {
+ display: false,
+ title: '',
+ text: '',
+ status: {}
+ },
+ breads: [
+ {
+ text: 'serviceGovernance',
+ href: ''
+ },
+ {
+ text: 'meshRule',
+ href: ''
+ }
+ ],
+ height: 0,
+ operations: operations,
+ meshRoutingRules: [],
+ template: '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]',
+ ruleText: '',
+ readonly: false,
+ headers: []
+ }),
+ methods: {
+ setHeaders: function () {
+ this.headers = [
+ {
+ text: this.$t('appName'),
+ value: 'application',
+ align: 'left'
+ },
+ {
+ text: this.$t('operation'),
+ value: 'operation',
+ sortable: false,
+ width: '115px'
+ }
+ ]
+ },
+ querySelections(v) {
+ if (this.timerID) {
+ clearTimeout(this.timerID)
+ }
+ // Simulated ajax query
+ this.timerID = setTimeout(() => {
+ if (v && v.length >= 4) {
+ this.searchLoading = true
+ this.typeAhead = this.$store.getters.getAppItems(v)
+ this.searchLoading = false
+ this.timerID = null
+ } else {
+ this.typeAhead = []
+ }
+ }, 500)
+ },
+ submit: function () {
+ if (!this.filter) {
+ this.$notify.error('application is needed')
+ return
+ }
+ this.filter = this.filter.trim()
+ this.search(true)
+ },
+ search: function (rewrite) {
+ let url = '/rules/route/mesh/?application' + '=' + this.filter
+ this.$axios.get(url)
+ .then(response => {
+ this.meshRoutingRules = response.data
+ if (rewrite) {
+ this.$router.push({path: 'meshRule', query: {application: this.filter}})
+ }
+ })
+ },
+ closeDialog: function () {
+ this.ruleText = this.template
+ this.updateId = ''
+ this.application = ''
+ this.dialog = false
+ this.readonly = false
+ },
+ openDialog: function () {
+ this.dialog = true
+ },
+ openWarn: function (title, text) {
+ this.warn.title = title
+ this.warn.text = text
+ this.warn.display = true
+ },
+ closeWarn: function () {
+ this.warn.title = ''
+ this.warn.text = ''
+ this.warn.display = false
+ },
+ saveItem: function () {
+ const rule = {}
+ rule.meshRule = this.ruleText
+ if (!this.application) {
+ this.$notify.error('application is required')
+ return
+ }
+ rule.application = this.application
+ let vm = this
+ if (this.updateId) {
+ if (this.updateId === 'close') {
+ this.closeDialog()
+ } else {
+ rule.id = this.updateId
+ this.$axios.put('/rules/route/mesh/' + rule.id, rule)
+ .then(response => {
+ if (response.status === 200) {
+ vm.search(vm.application, true)
+ vm.closeDialog()
+ vm.$notify.success('Update success')
+ }
+ })
+ }
+ } else {
+ this.$axios.post('/rules/route/mesh/', rule)
+ .then(response => {
+ if (response.status === 201) {
+ vm.search(vm.application, true)
+ vm.filter = vm.application
+ vm.closeDialog()
+ vm.$notify.success('Create success')
+ }
+ })
+ .catch(error => {
+ console.log(error)
+ })
+ }
+ },
+ itemOperation: function (icon, item) {
+ let itemId = item.application
+ switch (icon) {
+ case 'visibility':
+ this.$axios.get('/rules/route/mesh/' + itemId)
+ .then(response => {
+ let meshRoute = response.data
+ this.handleBalance(meshRoute, true)
+ this.updateId = 'close'
+ })
+ break
+ case 'edit':
+ let id = {}
+ id.id = itemId
+ this.$axios.get('/rules/route/mesh/' + itemId)
+ .then(response => {
+ let meshRoute = response.data
+ this.handleBalance(meshRoute, false)
+ this.updateId = itemId
+ })
+ break
+ case 'delete':
+ this.openWarn('warnDeleteMeshRule', 'application: ' + item.application)
+ this.warn.status.operation = 'delete'
+ this.warn.status.id = itemId
+ }
+ },
+ handleBalance: function (meshRoute, readonly) {
+ this.application = meshRoute.application
+ delete meshRoute.id
+ delete meshRoute.application
+ this.ruleText = meshRoute.meshRule
+ this.readonly = readonly
+ this.dialog = true
+ },
+ setHeight: function () {
+ this.height = window.innerHeight * 0.5
+ },
+ deleteItem: function (warnStatus) {
+ let id = warnStatus.id
+ let operation = warnStatus.operation
+ if (operation === 'delete') {
+ this.$axios.delete('/rules/route/mesh/' + id)
+ .then(response => {
+ if (response.status === 200) {
+ this.warn.display = false
+ this.search(this.filter, false)
+ this.$notify.success('Delete success')
+ }
+ })
+ }
+ }
+ },
+ created() {
+ this.setHeight()
+ },
+ computed: {
+ area() {
+ return this.$i18n.locale
+ }
+ },
+ watch: {
+ input(val) {
+ this.querySelections(val)
+ },
+ area() {
+ this.setHeaders()
+ }
+ },
+ mounted: function () {
+ this.setHeaders()
+ this.$store.dispatch('loadInstanceAppItems')
+ this.ruleText = this.template
+ let query = this.$route.query
+ let filter = null
+ Object.keys(query).forEach(function (key) {
+ if (key === 'application') {
+ filter = query[key]
+ }
+ })
+ if (filter !== null) {
+ this.filter = filter
+ this.search(false)
+ }
+ }
+
+ }
+</script>
diff --git a/dubbo-admin-ui/src/lang/en.js b/dubbo-admin-ui/src/lang/en.js
index c0d485f..f047218 100644
--- a/dubbo-admin-ui/src/lang/en.js
+++ b/dubbo-admin-ui/src/lang/en.js
@@ -20,6 +20,7 @@
serviceGovernance: 'Service Governance',
routingRule: 'Condition Rule',
tagRule: 'Tag Rule',
+ meshRule: 'Mesh Rule',
dynamicConfig: 'Dynamic Config',
accessControl: 'Black White List',
weightAdjust: 'Weight Adjust',
@@ -45,6 +46,9 @@
serialization: 'serialization',
appName: 'Application Name',
serviceName: 'Service Name',
+ registrySource: 'Registry Source',
+ instanceRegistry: 'Instance Registry',
+ interfaceRegistry: 'Interface Registry',
operation: 'Operation',
searchResult: 'Search Result',
search: 'Search',
@@ -61,6 +65,7 @@
ruleContent: 'RULE CONTENT',
createNewRoutingRule: 'Create New Routing Rule',
createNewTagRule: 'Create New Tag Rule',
+ createNewMeshRule: 'Create New Mesh Rule',
createNewDynamicConfigRule: 'Create New Dynamic Config Rule',
createNewWeightRule: 'Create New Weight Rule',
createNewLoadBalanceRule: 'Create new load balancing rule',
@@ -86,6 +91,7 @@
ipSearchHint: 'Find all services provided by the target server on the specified IP address',
appSearchHint: 'Input an application name to find all services provided by one particular application, * for all',
searchTagRule: 'Search Tag Rule by application name',
+ searchMeshRule: 'Search Mesh Rule by application name',
searchSingleMetrics: 'Search Metrics by IP',
searchBalanceRule: 'Search Balancing Rule',
noMetadataHint: 'There is no metadata available, please update to Dubbo2.7, or check your config center configuration in application.properties, please check ',
@@ -137,6 +143,7 @@
warnDeleteBalancing: 'Are you sure to Delete load balancing',
warnDeleteAccessControl: 'Are you sure to Delete access control',
warnDeleteTagRule: 'Are you sure to Delete tag rule',
+ warnDeleteMeshRule: 'Are you sure to Delete mesh rule',
warnDeleteWeightAdjust: 'Are you sure to Delete weight adjust',
configNameHint: "Application name the config belongs to, use 'global'(without quotes) for global config",
configContent: 'Config Content',
diff --git a/dubbo-admin-ui/src/lang/zh.js b/dubbo-admin-ui/src/lang/zh.js
index 786b494..084a129 100644
--- a/dubbo-admin-ui/src/lang/zh.js
+++ b/dubbo-admin-ui/src/lang/zh.js
@@ -22,6 +22,7 @@
serviceRelation: '服务关系',
routingRule: '条件路由',
tagRule: '标签路由',
+ meshRule: 'Mesh路由',
dynamicConfig: '动态配置',
accessControl: '黑白名单',
weightAdjust: '权重调整',
@@ -45,6 +46,9 @@
serialization: '序列化',
appName: '应用名',
serviceName: '服务名',
+ registrySource: '注册来源',
+ instanceRegistry: '应用级',
+ interfaceRegistry: '接口级',
operation: '操作',
searchResult: '查询结果',
search: '搜索',
@@ -61,6 +65,7 @@
ruleContent: '规则内容',
createNewRoutingRule: '创建新路由规则',
createNewTagRule: '创建新标签规则',
+ createMeshTagRule: '创建新mesh规则',
createNewDynamicConfigRule: '创建新动态配置规则',
createNewWeightRule: '新建权重规则',
createNewLoadBalanceRule: '新建负载均衡规则',
@@ -86,6 +91,7 @@
ipSearchHint: '在指定的IP地址上查找目标服务器提供的所有服务',
appSearchHint: '输入应用名称以查找由一个特定应用提供的所有服务, * 代表所有',
searchTagRule: '根据应用名搜索标签规则',
+ searchMeshRule: '根据应用名搜索mesh规则',
searchSingleMetrics: '输入IP搜索Metrics信息',
searchBalanceRule: '搜索负载均衡规则',
parameterList: '参数列表',
@@ -137,6 +143,7 @@
warnDeleteBalancing: '是否要删除负载均衡规则',
warnDeleteAccessControl: '是否要删除黑白名单',
warnDeleteTagRule: '是否要删除标签路由',
+ warnDeleteMeshRule: '是否要删除mesh路由',
warnDeleteWeightAdjust: '是否要删除权重规则',
configNameHint: '配置所属的应用名, global 表示全局配置',
configContent: '配置内容',
diff --git a/dubbo-admin-ui/src/router/index.js b/dubbo-admin-ui/src/router/index.js
index 1a4c2c1..6343d34 100644
--- a/dubbo-admin-ui/src/router/index.js
+++ b/dubbo-admin-ui/src/router/index.js
@@ -22,6 +22,7 @@
import TestMethod from '@/components/test/TestMethod'
import RoutingRule from '@/components/governance/RoutingRule'
import TagRule from '@/components/governance/TagRule'
+import MeshRule from '@/components/governance/MeshRule'
import AccessControl from '@/components/governance/AccessControl'
import LoadBalance from '@/components/governance/LoadBalance'
import WeightAdjust from '@/components/governance/WeightAdjust'
@@ -88,6 +89,14 @@
}
},
{
+ path: '/governance/meshRule',
+ name: 'MeshRule',
+ component: MeshRule,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
path: '/governance/access',
name: 'AccessControl',
component: AccessControl,
diff --git a/dubbo-admin-ui/src/store/index.js b/dubbo-admin-ui/src/store/index.js
index d553ce8..57484ba 100644
--- a/dubbo-admin-ui/src/store/index.js
+++ b/dubbo-admin-ui/src/store/index.js
@@ -71,6 +71,18 @@
})
},
/**
+ * Load instance registry application items from server, put results into storage.
+ */
+ loadInstanceAppItems ({commit}) {
+ Vue.prototype.$axios.get('/applications/instance')
+ .then(response => {
+ if (response.status === 200) {
+ const appItems = response.data
+ commit('setAppItems', appItems)
+ }
+ })
+ },
+ /**
* Load application items from consumer, put results into storage.
*/
loadConsumerItems ({commit}) {
diff --git a/pom.xml b/pom.xml
index eb253e8..b55697b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,7 +55,9 @@
<properties>
<revision>0.3.0</revision>
<main.basedir>${project.basedir}</main.basedir>
- <dubbo-version>2.7.12</dubbo-version>
+ <commons-lang3-version>3.7</commons-lang3-version>
+ <dubbo-version>3.0.2</dubbo-version>
+ <fastjson-version>1.2.67</fastjson-version>
<springfox-swagger-version>2.9.2</springfox-swagger-version>
<jacoco-version>0.8.2</jacoco-version>
<apollo-version>1.2.0</apollo-version>
@@ -104,9 +106,9 @@
</dependency>
<dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-serialization-kryo</artifactId>
- <version>${dubbo-version}</version>
+ <groupId>com.alibaba</groupId>
+ <artifactId>fastjson</artifactId>
+ <version>${fastjson-version}</version>
</dependency>
<dependency>