Merge branch 'develop' into service-test
diff --git a/dubbo-admin-backend/pom.xml b/dubbo-admin-backend/pom.xml
index 671f865..8d04e90 100644
--- a/dubbo-admin-backend/pom.xml
+++ b/dubbo-admin-backend/pom.xml
@@ -96,6 +96,12 @@
</dependency>
<dependency>
+ <groupId>org.apache.curator</groupId>
+ <artifactId>curator-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/CoderUtil.java
similarity index 82%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/CoderUtil.java
index ad01650..1245168 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/CoderUtil.java
@@ -17,15 +17,16 @@
package org.apache.dubbo.admin.common.util;
+import org.apache.dubbo.common.io.Bytes;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-public class MD5Util {
+public class CoderUtil {
- private static final Logger logger = LoggerFactory.getLogger(MD5Util.class);
+ private static final Logger logger = LoggerFactory.getLogger(CoderUtil.class);
private static MessageDigest md;
private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
@@ -55,6 +56,16 @@
return hash;
}
+ public static String MD5_32bit(byte[] input) {
+ if (input == null || input.length == 0) {
+ return null;
+ }
+ md.update(input);
+ byte[] digest = md.digest();
+ String hash = convertToString(digest);
+ return hash;
+ }
+
private static String convertToString(byte[] data) {
StringBuilder r = new StringBuilder(data.length * 2);
for (byte b : data) {
@@ -64,7 +75,7 @@
return r.toString();
}
- public static void main(String[] args) {
- System.out.println(MD5_16bit("fwjioejfiowejfiowjfiwfjowejfei"));
+ public static String decodeBase64(String source) {
+ return new String(Bytes.base642bytes(source));
}
}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
index 86d9d2b..ef2ef89 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
@@ -29,6 +29,7 @@
public static final String PATH_SEPARATOR = "/";
public static final String GROUP_KEY = "group";
public static final String CONFIG_KEY = "config";
+ public static final String DUBBO_PROPERTY = "dubbo.properties";
public static final String PROVIDER_SIDE = "provider";
public static final String CONSUMER_SIDE = "consumer";
public static final String CATEGORY_KEY = "category";
@@ -51,7 +52,8 @@
public static final String VERSION_KEY = "version";
public static final String PROVIDERS_CATEGORY = "providers";
public static final String CONSUMERS_CATEGORY = "consumers";
- public static final String SPECIFICATION_VERSION_KEY = "specVersion";
+ public static final String SPECIFICATION_VERSION_KEY = "release";
+ public static final String GLOBAL_CONFIG = "global";
public static final Set<String> CONFIGS = new HashSet<>();
static {
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
index a3c6405..491b35e 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
@@ -23,12 +23,14 @@
import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
import org.apache.dubbo.admin.registry.metadata.impl.NoOpMetadataCollector;
+import org.apache.dubbo.admin.service.ManagementService;
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.registry.Registry;
import org.apache.dubbo.registry.RegistryFactory;
+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;
@@ -41,18 +43,25 @@
public class ConfigCenter {
- @Value("${dubbo.config-center:}")
- private String configCenter;
- @Value("${dubbo.config-center.username:}")
- private String username;
- @Value("${dubbo.config-center.password:}")
- private String password;
- @Value("${dubbo.registry.address:}")
+ //centers in dubbo 2.7
+ @Value("${admin.config-center:}")
+ private String configCenter;
+
+ @Value("${admin.registry.address:}")
private String registryAddress;
- @Value("${dubbo.registry.group:}")
+
+ @Value("${admin.metadata.address:}")
+ private String metadataAddress;
+
+ @Value("${admin.registry.group:}")
private String group;
+ @Value("${admin.config-center.username:}")
+ private String username;
+ @Value("${admin.config-center.password:}")
+
+ private String password;
private static String globalConfigPath = "config/dubbo/dubbo.properties";
private static final Logger logger = LoggerFactory.getLogger(ConfigCenter.class);
@@ -62,6 +71,7 @@
private URL metadataUrl;
+
/*
* generate dynamic configuration client
*/
@@ -79,7 +89,8 @@
if (StringUtils.isNotEmpty(config)) {
Arrays.stream(config.split("\n")).forEach( s -> {
if(s.startsWith(Constants.REGISTRY_ADDRESS)) {
- registryUrl = formUrl(s.split("=")[1].trim(), group, username, password);
+ String registryAddress = s.split("=")[1].trim();
+ registryUrl = formUrl(registryAddress, group, username, password);
} else if (s.startsWith(Constants.METADATA_ADDRESS)) {
metadataUrl = formUrl(s.split("=")[1].trim(), group, username, password);
}
@@ -126,6 +137,11 @@
@DependsOn("governanceConfiguration")
MetaDataCollector getMetadataCollector() {
MetaDataCollector metaDataCollector = new NoOpMetadataCollector();
+ if (metadataUrl == null) {
+ if (StringUtils.isNotEmpty(metadataAddress)) {
+ metadataUrl = formUrl(metadataAddress, group, username, password);
+ }
+ }
if (metadataUrl != null) {
metaDataCollector = ExtensionLoader.getExtensionLoader(MetaDataCollector.class).getExtension(metadataUrl.getProtocol());
metaDataCollector.setUrl(metadataUrl);
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java
new file mode 100644
index 0000000..c846ce6
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java
@@ -0,0 +1,104 @@
+/*
+ * 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.common.exception.ParamValidationException;
+import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.model.dto.ConfigDTO;
+import org.apache.dubbo.admin.service.ManagementService;
+import org.apache.dubbo.admin.service.ProviderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+@RestController
+@RequestMapping("/api/{env}/manage")
+public class ManagementController {
+
+ private final ManagementService managementService;
+ private final ProviderService providerService;
+ private static Pattern CLASS_NAME_PATTERN = Pattern.compile("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)*[a-zA-Z_$][a-zA-Z\\d_$]*");
+
+
+ @Autowired
+ public ManagementController(ManagementService managementService, ProviderService providerService) {
+ this.managementService = managementService;
+ this.providerService = providerService;
+ }
+
+ @RequestMapping(value ="/config", method = RequestMethod.POST)
+ @ResponseStatus(HttpStatus.CREATED)
+ public boolean createConfig(@RequestBody ConfigDTO config, @PathVariable String env) {
+ managementService.setConfig(config);
+ return true;
+ }
+
+ @RequestMapping(value = "/config/{key}", method = RequestMethod.PUT)
+ public boolean updateConfig(@PathVariable String key, @RequestBody ConfigDTO configDTO, @PathVariable String env) {
+ if (key == null) {
+ throw new ParamValidationException("Unknown ID!");
+ }
+ String exitConfig = managementService.getConfig(key);
+ if (exitConfig == null) {
+ throw new ResourceNotFoundException("Unknown ID!"); }
+ return managementService.updateConfig(configDTO);
+ }
+
+ @RequestMapping(value = "/config/{key}", method = RequestMethod.GET)
+ public List<ConfigDTO> getConfig(@PathVariable String key, @PathVariable String env) {
+ Set<String> query = new HashSet<>();
+ List<ConfigDTO> configDTOs = new ArrayList<>();
+ if (key.equals(Constants.ANY_VALUE)) {
+ query = providerService.findApplications();
+ query.add("global");
+ } else {
+ query.add(key);
+ }
+ for (String q : query) {
+ String config = managementService.getConfig(q);
+ if (config == null) {
+ continue;
+ }
+ ConfigDTO configDTO = new ConfigDTO();
+ configDTO.setKey(q);
+ configDTO.setConfig(config);
+ configDTO.setPath(managementService.getConfigPath(q));
+ if (Constants.GLOBAL_CONFIG.equals(q)) {
+ configDTO.setScope(Constants.GLOBAL_CONFIG);
+ } else if(CLASS_NAME_PATTERN.matcher(q).matches()){
+ configDTO.setScope(Constants.SERVICE);
+ } else {
+ configDTO.setScope(Constants.APPLICATION);
+ }
+ configDTOs.add(configDTO);
+ }
+ return configDTOs;
+ }
+
+ @RequestMapping(value = "/config/{key}", method = RequestMethod.DELETE)
+ public boolean deleteConfig(@PathVariable String key, @PathVariable String env) {
+ return managementService.deleteConfig(key);
+ }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
index 87856ef..dfbc607 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.admin.controller;
+import com.ctrip.framework.apollo.core.enums.Env;
import com.google.gson.Gson;
import org.apache.dubbo.admin.common.util.ConvertUtil;
import org.apache.dubbo.admin.model.domain.Consumer;
@@ -26,7 +27,6 @@
import org.apache.dubbo.admin.service.ConsumerService;
import org.apache.dubbo.admin.service.ProviderService;
import org.apache.dubbo.admin.common.util.Constants;
-import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
import org.springframework.beans.factory.annotation.Autowired;
@@ -38,7 +38,7 @@
@RestController
-@RequestMapping("/api/{env}/service")
+@RequestMapping("/api/{env}")
public class ServiceController {
private final ProviderService providerService;
@@ -50,7 +50,7 @@
this.consumerService = consumerService;
}
- @RequestMapping(method = RequestMethod.GET)
+ @RequestMapping( value = "/service", method = RequestMethod.GET)
public Set<ServiceDTO> searchService(@RequestParam String pattern,
@RequestParam String filter,@PathVariable String env) {
return providerService.getServiceDTOS(pattern, filter, env);
@@ -58,7 +58,7 @@
- @RequestMapping(value = "/{service}", method = RequestMethod.GET)
+ @RequestMapping(value = "/service/{service}", method = RequestMethod.GET)
public ServiceDetailDTO serviceDetail(@PathVariable String service, @PathVariable String env) {
service = service.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
List<Provider> providers = providerService.findByService(service);
@@ -88,4 +88,14 @@
serviceDetailDTO.setApplication(application);
return serviceDetailDTO;
}
+
+ @RequestMapping(value = "/services", method = RequestMethod.GET)
+ public Set<String> allServices(@PathVariable String env) {
+ return providerService.findServices();
+ }
+
+ @RequestMapping(value = "/applications", method = RequestMethod.GET)
+ public Set<String> allApplications(@PathVariable String env) {
+ return providerService.findApplications();
+ }
}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ConfigDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ConfigDTO.java
new file mode 100644
index 0000000..439fab8
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ConfigDTO.java
@@ -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.
+ */
+
+package org.apache.dubbo.admin.model.dto;
+
+public class ConfigDTO {
+
+ private String key;
+ private String config;
+ private String scope;
+ private String path;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getConfig() {
+ return config;
+ }
+
+ public void setConfig(String config) {
+ this.config = config;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
index c6ed397..21e739b 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
@@ -40,4 +40,8 @@
boolean deleteConfig(String group, String key);
+ String getPath(String key);
+
+ String getPath(String group, String key);
+
}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java
index 13d4b2e..58ce20c 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java
@@ -27,19 +27,19 @@
@SPI("apollo")
public class ApolloConfiguration implements GovernanceConfiguration {
- @Value("${dubbo.apollo.token}")
+ @Value("${admin.apollo.token}")
private String token;
- @Value("${dubbo.apollo.cluster}")
+ @Value("${admin.apollo.cluster}")
private String cluster;
- @Value("${dubbo.apollo.namespace}")
+ @Value("${admin.apollo.namespace}")
private String namespace;
- @Value("${dubbo.apollo.env}")
+ @Value("${admin.apollo.env}")
private String env;
- @Value("${dubbo.apollo.appId}")
+ @Value("${admin.apollo.appId}")
private String appId;
private URL url;
@@ -109,4 +109,14 @@
client.removeItem(appId, env, cluster, group, key, "admin");
return true;
}
+
+ @Override
+ public String getPath(String key) {
+ return null;
+ }
+
+ @Override
+ public String getPath(String group, String key) {
+ return null;
+ }
}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java
index 85dca2f..5c4fd18 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java
@@ -66,4 +66,14 @@
public boolean deleteConfig(String group, String key) {
return false;
}
+
+ @Override
+ public String getPath(String key) {
+ return null;
+ }
+
+ @Override
+ public String getPath(String group, String key) {
+ return null;
+ }
}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java
index 0ba847a..1eed438 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java
@@ -17,16 +17,16 @@
package org.apache.dubbo.admin.registry.config.impl;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
-import org.apache.dubbo.admin.common.util.Constants;
-import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.URL;
-
public class ZookeeperConfiguration implements GovernanceConfiguration {
private static final Logger logger = LoggerFactory.getLogger(ZookeeperConfiguration.class);
@@ -46,10 +46,13 @@
@Override
public void init() {
+ if (url == null) {
+ throw new IllegalStateException("server url is null, cannot init");
+ }
CuratorFrameworkFactory.Builder zkClientBuilder = CuratorFrameworkFactory.builder().
connectString(url.getAddress()).
retryPolicy(new ExponentialBackoffRetry(1000, 3));
- if(StringUtils.isNotEmpty(url.getUsername()) && StringUtils.isNotEmpty(url.getPassword())){
+ if (StringUtils.isNotEmpty(url.getUsername()) && StringUtils.isNotEmpty(url.getPassword())) {
// add authorization
String auth = url.getUsername() + ":" + url.getPassword();
zkClientBuilder.authorization("digest", auth.getBytes());
@@ -80,6 +83,9 @@
@Override
public String setConfig(String group, String key, String value) {
+ if (key == null || value == null) {
+ throw new IllegalArgumentException("key or value cannot be null");
+ }
String path = getNodePath(key, group);
try {
if (zkClient.checkExists().forPath(path) == null) {
@@ -95,6 +101,9 @@
@Override
public String getConfig(String group, String key) {
+ if (key == null) {
+ throw new IllegalArgumentException("key cannot be null");
+ }
String path = getNodePath(key, group);
try {
@@ -110,16 +119,33 @@
@Override
public boolean deleteConfig(String group, String key) {
+ if (key == null) {
+ throw new IllegalArgumentException("key cannot be null");
+ }
String path = getNodePath(key, group);
try {
zkClient.delete().forPath(path);
} catch (Exception e) {
logger.error(e.getMessage(), e);
+ return false;
}
return true;
}
+ @Override
+ public String getPath(String key) {
+ return getNodePath(key, null);
+ }
+
+ @Override
+ public String getPath(String group, String key) {
+ return getNodePath(key, group);
+ }
+
private String getNodePath(String path, String group) {
+ if (path == null) {
+ throw new IllegalArgumentException("path cannot be null");
+ }
return toRootDir(group) + path;
}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ManagementService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ManagementService.java
new file mode 100644
index 0000000..9d0a388
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ManagementService.java
@@ -0,0 +1,34 @@
+/*
+ * 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.ConfigDTO;
+
+public interface ManagementService {
+
+
+ void setConfig(ConfigDTO config);
+
+ String getConfig(String key);
+
+ String getConfigPath(String key);
+
+ boolean updateConfig(ConfigDTO configDTO);
+
+ boolean deleteConfig(String key);
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
index 01a79e4..b035b13 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
@@ -52,7 +52,7 @@
*
* @return list of all provider's service name
*/
- List<String> findServices();
+ Set<String> findServices();
String findServiceVersion(String serviceName, String application);
@@ -88,7 +88,7 @@
List<String> findServicesByAddress(String providerAddress);
- List<String> findApplications();
+ Set<String> findApplications();
/**
* Get provider list with specific application name.
@@ -117,4 +117,4 @@
*/
Set<ServiceDTO> getServiceDTOS(String pattern, String filter, String env);
-}
\ No newline at end of file
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
index 7a4a676..1cd7bb5 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
@@ -16,7 +16,7 @@
*/
package org.apache.dubbo.admin.service;
-import org.apache.dubbo.admin.common.util.MD5Util;
+import org.apache.dubbo.admin.common.util.CoderUtil;
import org.apache.dubbo.admin.common.util.Tool;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
@@ -134,7 +134,7 @@
if (URL_IDS_MAPPER.containsKey(url.toFullString())) {
ids.put(URL_IDS_MAPPER.get(url.toFullString()), url);
} else {
- String md5 = MD5Util.MD5_16bit(url.toFullString());
+ String md5 = CoderUtil.MD5_16bit(url.toFullString());
ids.put(md5, url);
URL_IDS_MAPPER.putIfAbsent(url.toFullString(), md5);
}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java
new file mode 100644
index 0000000..d43e6de
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java
@@ -0,0 +1,82 @@
+/*
+ * 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.dto.ConfigDTO;
+import org.apache.dubbo.admin.service.ManagementService;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ManagementServiceImpl extends AbstractService implements ManagementService {
+
+
+ private static String globalConfigPath = "config/dubbo/dubbo.properties";
+
+ @Override
+ public void setConfig(ConfigDTO config) {
+ if (Constants.GLOBAL_CONFIG.equals(config.getKey())) {
+ dynamicConfiguration.setConfig(globalConfigPath, config.getConfig());
+ } else {
+ dynamicConfiguration.setConfig(getPath(config.getKey()), config.getConfig());
+ }
+ }
+
+ @Override
+ public String getConfig(String key) {
+ if (Constants.GLOBAL_CONFIG.equals(key)) {
+ return dynamicConfiguration.getConfig(globalConfigPath);
+ }
+ return dynamicConfiguration.getConfig(getPath(key));
+ }
+
+ @Override
+ public String getConfigPath(String key) {
+ if (Constants.GLOBAL_CONFIG.equals(key)) {
+ return dynamicConfiguration.getPath(globalConfigPath);
+ }
+ return dynamicConfiguration.getPath(getPath(key));
+ }
+
+ @Override
+ public boolean updateConfig(ConfigDTO configDTO) {
+ String key = configDTO.getKey();
+ if (Constants.GLOBAL_CONFIG.equals(key)) {
+ dynamicConfiguration.setConfig(globalConfigPath, configDTO.getConfig());
+ } else {
+ dynamicConfiguration.setConfig(getPath(key), configDTO.getConfig());
+ }
+ return true;
+ }
+
+ @Override
+ public boolean deleteConfig(String key) {
+ if (Constants.GLOBAL_CONFIG.equals(key)) {
+ dynamicConfiguration.deleteConfig(globalConfigPath);
+ } else {
+ dynamicConfiguration.deleteConfig(getPath(key));
+ }
+ return true;
+ }
+
+ private String getPath(String key) {
+ return Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR
+ + Constants.DUBBO_PROPERTY;
+ }
+
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
index 0786b8c..98e3e63 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
@@ -253,8 +253,8 @@
}
@Override
- public List<String> findServices() {
- List<String> ret = new ArrayList<String>();
+ public Set<String> findServices() {
+ Set<String> ret = new HashSet<>();
ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
if (providerUrls != null){
ret.addAll(providerUrls.keySet());
@@ -413,8 +413,8 @@
}
@Override
- public List<String> findApplications() {
- List<String> ret = new ArrayList<String>();
+ public Set<String> findApplications() {
+ Set<String> ret = new HashSet<>();
ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
if (providerUrls == null){
return ret;
@@ -568,7 +568,7 @@
}
} else {
// filter with fuzzy search
- List<String> candidates = Collections.emptyList();
+ Set<String> candidates = Collections.emptySet();
if (Constants.SERVICE.equals(pattern)) {
candidates = findServices();
} else if (Constants.APPLICATION.equals(pattern)) {
diff --git a/dubbo-admin-backend/src/main/resources/application.properties b/dubbo-admin-backend/src/main/resources/application.properties
index 28fa8d0..514345f 100644
--- a/dubbo-admin-backend/src/main/resources/application.properties
+++ b/dubbo-admin-backend/src/main/resources/application.properties
@@ -15,13 +15,16 @@
# limitations under the License.
#
-dubbo.config-center.username=username
-dubbo.config-center.password=password
-dubbo.config-center=zookeeper://127.0.0.1:2181
-dubbo.registry.group=dubbo
-dubbo.registry.address=zookeeper://127.0.0.1:2181
-dubbo.apollo.token=e16e5cd903fd0c97a116c873b448544b9d086de9
-dubbo.apollo.appId=test
-dubbo.apollo.env=dev
-dubbo.apollo.cluster=default
-dubbo.apollo.namespace=dubbo
+# centers in dubbo2.7
+admin.registry.address=zookeeper://127.0.0.1:2181
+admin.config-center=zookeeper://127.0.0.1:2181
+admin.metadata.address=zookeeper://127.0.0.1:2181
+
+
+
+admin.registry.group=dubbo
+admin.apollo.token=e16e5cd903fd0c97a116c873b448544b9d086de9
+admin.apollo.appId=test
+admin.apollo.env=dev
+admin.apollo.cluster=default
+admin.apollo.namespace=dubbo
diff --git a/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java
new file mode 100644
index 0000000..7c2c90f
--- /dev/null
+++ b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.config.impl;
+
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.NetUtils;
+
+import org.apache.curator.test.TestingServer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class ZookeeperConfigurationTest {
+
+ private TestingServer zkServer;
+ private ZookeeperConfiguration configuration;
+ private URL registryUrl;
+
+ @Before
+ public void setup() throws Exception {
+ int zkServerPort = NetUtils.getAvailablePort();
+ zkServer = new TestingServer(zkServerPort, true);
+ registryUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort);
+
+ configuration = new ZookeeperConfiguration();
+ try {
+ configuration.init();
+ fail("init should fail before setting registryUrl");
+ } catch (IllegalStateException e) {
+ }
+
+ configuration.setUrl(registryUrl);
+ configuration.init();
+ }
+
+ @Test
+ public void testGetSetConfig() {
+ configuration.setConfig("test_key", "test_value");
+ assertEquals("test_value", configuration.getConfig("test_key"));
+ assertEquals(null, configuration.getConfig("not_exist_key"));
+
+
+ configuration.setConfig("test_group", "test_key", "test_group_value");
+ assertEquals("test_group_value", configuration.getConfig("test_group", "test_key"));
+
+ assertEquals(null, configuration.getConfig("test_group", "not_exist_key"));
+
+ try {
+ configuration.getConfig(null);
+ fail("should throw IllegalArgumentException for null key");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ configuration.setConfig("test_null", null);
+ fail("should throw IllegalArgumentException for null key");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testDeleteConfig() {
+ assertEquals(false, configuration.deleteConfig("not_exist_key"));
+ configuration.setConfig("test_delete", "test_value");
+ assertEquals("test_value", configuration.getConfig("test_delete"));
+ configuration.deleteConfig("test_delete");
+ assertEquals(null, configuration.getConfig("test_delete"));
+
+ assertEquals(false, configuration.deleteConfig("test_group", "not_exist_key"));
+ configuration.setConfig("test_group", "test_delete", "test_value");
+ assertEquals("test_value", configuration.getConfig("test_group", "test_delete"));
+ configuration.deleteConfig("test_group", "test_delete");
+ assertEquals(null, configuration.getConfig("test_group", "test_delete"));
+
+ try {
+ configuration.deleteConfig(null);
+ fail("should throw IllegalArgumentException for null key");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testGetPath() {
+ assertEquals(Constants.PATH_SEPARATOR + Constants.DEFAULT_ROOT + Constants.PATH_SEPARATOR + "test_key",
+ configuration.getPath("test_key"));
+ try {
+ configuration.getPath(null);
+ fail("should throw IllegalArgumentException for null path");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ zkServer.stop();
+ }
+
+}
diff --git a/dubbo-admin-frontend/src/api/menu.js b/dubbo-admin-frontend/src/api/menu.js
index 6f5ccac..05c058c 100644
--- a/dubbo-admin-frontend/src/api/menu.js
+++ b/dubbo-admin-frontend/src/api/menu.js
@@ -32,8 +32,8 @@
},
{ title: 'serviceTest', path: '/test', icon: 'code', badge: 'feature' },
{ title: 'serviceMock', path: '/mock', icon: 'build', badge: 'feature' },
- { title: 'metrics', path: '/metrics', icon: 'show_chart', badge: 'feature' }
-
+ { title: 'metrics', path: '/metrics', icon: 'show_chart', badge: 'feature' },
+ { title: 'configManage', path: '/management', icon: 'build', badge: 'feature' }
]
export default Menu
diff --git a/dubbo-admin-frontend/src/components/Management.vue b/dubbo-admin-frontend/src/components/Management.vue
new file mode 100644
index 0000000..f80d03b
--- /dev/null
+++ b/dubbo-admin-frontend/src/components/Management.vue
@@ -0,0 +1,293 @@
+<!--
+ - 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 xs12 >
+ <search id="serviceSearch" v-model="filter" :submit="submit" :label="$t('searchDubboConfig')" :hint="$t('configNameHint')"></search>
+ </v-flex>
+ </v-layout>
+ <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="dubboConfig"
+ hide-actions
+ class="elevation-0"
+ >
+ <template slot="items" slot-scope="props">
+ <td class="text-xs-left">
+ <v-tooltip bottom >
+ <span slot="activator">
+ {{props.item.key}}
+ </span>
+ <span>{{props.item.path}}</span>
+ </v-tooltip>
+ </td>
+ <td class="text-xs-left">
+ <v-chip
+ :color="getColor(props.item.scope)"
+ text-color="white">
+ {{props.item.scope}}
+ </v-chip>
+ </td>
+ <td class="text-xs-center px-0">
+ <v-tooltip bottom v-for="op in operations" :key="op.id">
+ <v-icon small class="mr-2" slot="activator" @click="itemOperation(op.icon, props.item)">
+ {{op.icon}}
+ </v-icon>
+ <span>{{$t(op.tooltip)}}</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('createNewDubboConfig')}}</span>
+ </v-card-title>
+ <v-card-text >
+ <v-text-field
+ :label="$t('appName')"
+ :hint="$t('configNameHint')"
+ v-model="key"
+ ></v-text-field>
+
+ <v-subheader class="pa-0 mt-3">{{$t('ruleContent')}}</v-subheader>
+ <ace-editor lang="properties" v-model="rule" :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) + this.warnStatus.id}}</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">{{$t('cancel')}}</v-btn>
+ <v-btn depressed color="primary" @click.native="deleteItem(warnStatus)">{{$t('confirm')}}</v-btn>
+ </v-card-actions>
+ </v-card>
+ </v-dialog>
+
+ </v-container>
+</template>
+
+<script>
+ import AceEditor from '@/components/public/AceEditor'
+ import Search from '@/components/public/Search'
+ export default {
+ name: 'Management',
+ components: {
+ AceEditor,
+ Search
+ },
+ data: () => ({
+ configCenter: '',
+ rule: '',
+ updateId: '',
+ key: '',
+ filter: '',
+ readonly: false,
+ dialog: false,
+ operations: [
+ {id: 0, icon: 'visibility', tooltip: 'view'},
+ {id: 1, icon: 'edit', tooltip: 'edit'},
+ {id: 3, icon: 'delete', tooltip: 'delete'}
+ ],
+ warn: {
+ display: false,
+ title: '',
+ text: '',
+ status: {}
+ },
+ warnStatus: {},
+ dubboConfig: [],
+ headers: []
+ }),
+ methods: {
+ setHeaders () {
+ this.headers = [
+ {
+ text: this.$t('name'),
+ value: 'name',
+ align: 'left'
+ },
+ {
+ text: this.$t('scope'),
+ value: 'scope',
+ sortable: false
+ },
+ {
+ text: this.$t('operation'),
+ value: 'operation',
+ sortable: false,
+ width: '115px'
+ }
+ ]
+ },
+ itemOperation (icon, item) {
+ switch (icon) {
+ case 'visibility':
+ this.dialog = true
+ this.rule = item.config
+ this.key = item.key
+ this.readonly = true
+ this.updateId = 'close'
+ break
+ case 'edit':
+ this.dialog = true
+ this.rule = item.config
+ this.key = item.key
+ this.updateId = item.key
+ this.readonly = false
+ break
+ case 'delete':
+ this.openWarn('warnDeleteConfig')
+ this.warnStatus.id = item.key
+ }
+ },
+ deleteItem: function (warnStatus) {
+ this.$axios.delete('/manage/config/' + warnStatus.id)
+ .then(response => {
+ if (response.status === 200) {
+ this.warn.display = false
+ this.search(this.filter)
+ this.$notify.success('Delete success')
+ }
+ })
+ },
+ closeDialog: function () {
+ this.rule = ''
+ this.key = ''
+ 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 () {
+ let configDTO = {}
+ if (!this.key) {
+ this.$notify.error('Config key is needed')
+ return
+ }
+ configDTO.key = this.key
+ configDTO.config = this.rule
+ let vm = this
+ if (this.updateId) {
+ if (this.updateId === 'close') {
+ this.closeDialog()
+ } else {
+ this.$axios.put('/manage/config/' + this.updateId, configDTO)
+ .then(response => {
+ if (response.status === 200) {
+ vm.search(vm.key)
+ vm.filter = vm.key
+ this.closeDialog()
+ this.$notify.success('Update success')
+ }
+ })
+ }
+ } else {
+ this.$axios.post('/manage/config/', configDTO)
+ .then(response => {
+ if (response.status === 201) {
+ vm.search(vm.key)
+ vm.filter = vm.key
+ vm.closeDialog()
+ vm.$notify.success('Create success')
+ }
+ })
+ }
+ },
+ getColor (scope) {
+ if (scope === 'global') {
+ return 'red'
+ }
+ if (scope === 'application') {
+ return 'green'
+ }
+ if (scope === 'service') {
+ return 'blue'
+ }
+ },
+ submit () {
+ this.filter = this.filter.trim()
+ this.search(this.filter)
+ },
+ search (filter) {
+ this.$axios.get('/manage/config/' + filter)
+ .then(response => {
+ if (response.status === 200) {
+ this.dubboConfig = response.data
+ this.$router.push({path: 'management', query: {key: filter}})
+ }
+ })
+ }
+ },
+ mounted () {
+ this.setHeaders()
+ let query = this.$route.query
+ let filter = null
+ Object.keys(query).forEach(function (key) {
+ if (key === 'key') {
+ filter = query[key]
+ }
+ })
+ if (filter !== null) {
+ this.filter = filter
+ } else {
+ this.filter = 'global'
+ }
+ this.search(this.filter)
+ }
+ }
+</script>
+
+<style scoped>
+
+</style>
diff --git a/dubbo-admin-frontend/src/components/ServiceSearch.vue b/dubbo-admin-frontend/src/components/ServiceSearch.vue
index 293c6ce..6d42be3 100644
--- a/dubbo-admin-frontend/src/components/ServiceSearch.vue
+++ b/dubbo-admin-frontend/src/components/ServiceSearch.vue
@@ -312,18 +312,19 @@
pattern = 'service'
this.search(this.filter, pattern, true)
}
- this.$axios.get('/service', {
- params: {
- pattern: 'service',
- filter: '*'
- }
- }).then(response => {
- let length = response.data.length
- for (let i = 0; i < length; i++) {
- vm.serviceItem.push(response.data[i].service)
- vm.appItem.push(response.data[i].appName)
- }
- })
+ this.$axios.get('/services')
+ .then(response => {
+ if (response.status === 200) {
+ vm.serviceItem = response.data
+ }
+ })
+
+ this.$axios.get('/applications')
+ .then(response => {
+ if (response.status === 200) {
+ vm.appItem = response.data
+ }
+ })
}
}
diff --git a/dubbo-admin-frontend/src/components/governance/TagRule.vue b/dubbo-admin-frontend/src/components/governance/TagRule.vue
index e776576..dbda2f6 100644
--- a/dubbo-admin-frontend/src/components/governance/TagRule.vue
+++ b/dubbo-admin-frontend/src/components/governance/TagRule.vue
@@ -78,14 +78,14 @@
</v-card>
</v-dialog>
- <v-dialog v-model="warn" persistent max-width="500px">
+ <v-dialog v-model="warn.display" persistent max-width="500px">
<v-card>
- <v-card-title class="headline">{{$t(this.warnTitle)}}</v-card-title>
- <v-card-text >{{this.warnText}}</v-card-text>
+ <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(warnStatus)">CONFIRM</v-btn>
+ <v-btn depressed color="primary" @click.native="deleteItem(warn.status)">{{$t('confirm')}}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
@@ -110,12 +110,14 @@
pattern: 'Service',
filter: '',
dialog: false,
- warn: false,
updateId: '',
application: '',
- warnTitle: '',
- warnText: '',
- warnStatus: {},
+ warn: {
+ display: false,
+ title: '',
+ text: '',
+ status: {}
+ },
height: 0,
operations: operations,
tagRoutingRules: [
@@ -179,14 +181,14 @@
this.dialog = true
},
openWarn: function (title, text) {
- this.warnTitle = title
- this.warnText = text
- this.warn = true
+ this.warn.title = title
+ this.warn.text = text
+ this.warn.display = true
},
closeWarn: function () {
- this.warnTitle = ''
- this.warnText = ''
- this.warn = false
+ this.warn.title = ''
+ this.warn.text = ''
+ this.warn.display = false
},
saveItem: function () {
let rule = yaml.safeLoad(this.ruleText)
@@ -248,18 +250,18 @@
break
case 'block':
this.openWarn(' Are you sure to block Tag Rule', 'application: ' + item.application)
- this.warnStatus.operation = 'disable'
- this.warnStatus.id = itemId
+ this.warn.status.operation = 'disable'
+ this.warn.status.id = itemId
break
case 'check_circle_outline':
this.openWarn(' Are you sure to enable Tag Rule', 'application: ' + item.application)
- this.warnStatus.operation = 'enable'
- this.warnStatus.id = itemId
+ this.warn.status.operation = 'enable'
+ this.warn.status.id = itemId
break
case 'delete':
this.openWarn(' Are you sure to Delete Tag Rule', 'application: ' + item.application)
- this.warnStatus.operation = 'delete'
- this.warnStatus.id = itemId
+ this.warn.status.operation = 'delete'
+ this.warn.status.id = itemId
}
},
handleBalance: function (tagRoute, readonly) {
@@ -284,7 +286,7 @@
this.$axios.delete('/rules/route/tag/' + id)
.then(response => {
if (response.status === 200) {
- this.warn = false
+ this.warn.display = false
this.search(this.filter, false)
this.$notify.success('Delete success')
}
@@ -293,7 +295,7 @@
this.$axios.put('/rules/route/tag/disable/' + id)
.then(response => {
if (response.status === 200) {
- this.warn = false
+ this.warn.display = false
this.search(this.filter, false)
this.$notify.success('Disable success')
}
@@ -302,7 +304,7 @@
this.$axios.put('/rules/route/tag/enable/' + id)
.then(response => {
if (response.status === 200) {
- this.warn = false
+ this.warn.display = false
this.search(this.filter, false)
this.$notify.success('Enable success')
}
diff --git a/dubbo-admin-frontend/src/components/public/Search.vue b/dubbo-admin-frontend/src/components/public/Search.vue
index 6ace1e9..15e3432 100644
--- a/dubbo-admin-frontend/src/components/public/Search.vue
+++ b/dubbo-admin-frontend/src/components/public/Search.vue
@@ -21,6 +21,7 @@
<v-layout row wrap >
<v-text-field
:label="label" clearable
+ :hint="hint"
v-bind:value="value"
v-on:input="$emit('input', $event)"></v-text-field>
<v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn>
@@ -41,6 +42,10 @@
label: {
type: String,
default: ''
+ },
+ hint: {
+ type: String,
+ default: ''
}
},
data: () => ({
diff --git a/dubbo-admin-frontend/src/lang/en.js b/dubbo-admin-frontend/src/lang/en.js
index 593206c..2b771d7 100644
--- a/dubbo-admin-frontend/src/lang/en.js
+++ b/dubbo-admin-frontend/src/lang/en.js
@@ -114,5 +114,13 @@
rowsPerPageText: 'Rows per page:'
},
noDataText: 'No data available'
- }
+ },
+ configManage: 'Configuration Management',
+ configCenterAddress: 'ConfigCenter Address',
+ searchDubboConfig: 'Search Dubbo Config',
+ createNewDubboConfig: 'Create New Dubbo Config',
+ scope: 'Scope',
+ name: 'Name',
+ warnDeleteConfig: ' Are you sure to Delete Dubbo Config: ',
+ configNameHint: "Application name the config belongs to, use 'global'(without quotes) for global config"
}
diff --git a/dubbo-admin-frontend/src/lang/zh.js b/dubbo-admin-frontend/src/lang/zh.js
index fc28529..16517d8 100644
--- a/dubbo-admin-frontend/src/lang/zh.js
+++ b/dubbo-admin-frontend/src/lang/zh.js
@@ -114,5 +114,13 @@
rowsPerPageText: '每页行数:'
},
noDataText: '无可用数据'
- }
+ },
+ configManage: '配置管理',
+ configCenterAddress: '配置中心地址',
+ searchDubboConfig: '搜索Dubbo配置',
+ createNewDubboConfig: '新建Dubbo配置',
+ scope: '范围',
+ name: '名称',
+ warnDeleteConfig: ' 是否要删除Dubbo配置: ',
+ configNameHint: '配置所属的应用名, global 表示全局配置'
}
diff --git a/dubbo-admin-frontend/src/router/index.js b/dubbo-admin-frontend/src/router/index.js
index adfde47..35f8a90 100644
--- a/dubbo-admin-frontend/src/router/index.js
+++ b/dubbo-admin-frontend/src/router/index.js
@@ -29,6 +29,7 @@
import ServiceTest from '@/components/test/ServiceTest'
import ServiceMock from '@/components/test/ServiceMock'
import ServiceMetrics from '@/components/metrics/ServiceMetrics'
+import Management from '@/components/Management'
Vue.use(Router)
@@ -92,6 +93,11 @@
path: '/metrics',
name: 'ServiceMetrics',
component: ServiceMetrics
+ },
+ {
+ path: '/management',
+ name: 'Management',
+ component: Management
}
]
diff --git a/pom.xml b/pom.xml
index ee4d1b0..c858050 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,6 +58,7 @@
<commons-lang3-version>3.7</commons-lang3-version>
<dubbo-version>2.7.0-SNAPSHOT</dubbo-version>
<curator-version>2.12.0</curator-version>
+ <curator-test-version>2.12.0</curator-test-version>
<fastjson-version>1.2.46</fastjson-version>
<springfox-swagger-version>2.9.2</springfox-swagger-version>
<netty-version>4.1.30.Final</netty-version>
@@ -102,6 +103,13 @@
<artifactId>curator-framework</artifactId>
<version>${curator-version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.curator</groupId>
+ <artifactId>curator-test</artifactId>
+ <version>${curator-test-version}</version>
+ </dependency>
+
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>