提交 60bfd8ec 编写于 作者: N nzomkxia

Merge branch 'develop' into service-test

...@@ -95,6 +95,12 @@ ...@@ -95,6 +95,12 @@
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-test</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId> <artifactId>springfox-swagger2</artifactId>
......
...@@ -17,15 +17,16 @@ ...@@ -17,15 +17,16 @@
package org.apache.dubbo.admin.common.util; 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.Logger;
import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.logger.LoggerFactory;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; 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 MessageDigest md;
private static final char[] hexCode = "0123456789ABCDEF".toCharArray(); private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
...@@ -55,6 +56,16 @@ public class MD5Util { ...@@ -55,6 +56,16 @@ public class MD5Util {
return hash; 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) { private static String convertToString(byte[] data) {
StringBuilder r = new StringBuilder(data.length * 2); StringBuilder r = new StringBuilder(data.length * 2);
for (byte b : data) { for (byte b : data) {
...@@ -64,7 +75,7 @@ public class MD5Util { ...@@ -64,7 +75,7 @@ public class MD5Util {
return r.toString(); return r.toString();
} }
public static void main(String[] args) { public static String decodeBase64(String source) {
System.out.println(MD5_16bit("fwjioejfiowejfiowjfiwfjowejfei")); return new String(Bytes.base642bytes(source));
} }
} }
...@@ -29,6 +29,7 @@ public class Constants { ...@@ -29,6 +29,7 @@ public class Constants {
public static final String PATH_SEPARATOR = "/"; public static final String PATH_SEPARATOR = "/";
public static final String GROUP_KEY = "group"; public static final String GROUP_KEY = "group";
public static final String CONFIG_KEY = "config"; 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 PROVIDER_SIDE = "provider";
public static final String CONSUMER_SIDE = "consumer"; public static final String CONSUMER_SIDE = "consumer";
public static final String CATEGORY_KEY = "category"; public static final String CATEGORY_KEY = "category";
...@@ -51,7 +52,8 @@ public class Constants { ...@@ -51,7 +52,8 @@ public class Constants {
public static final String VERSION_KEY = "version"; public static final String VERSION_KEY = "version";
public static final String PROVIDERS_CATEGORY = "providers"; public static final String PROVIDERS_CATEGORY = "providers";
public static final String CONSUMERS_CATEGORY = "consumers"; 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<>(); public static final Set<String> CONFIGS = new HashSet<>();
static { static {
......
...@@ -23,12 +23,14 @@ import org.apache.dubbo.admin.common.util.Constants; ...@@ -23,12 +23,14 @@ import org.apache.dubbo.admin.common.util.Constants;
import org.apache.dubbo.admin.registry.config.GovernanceConfiguration; import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
import org.apache.dubbo.admin.registry.metadata.MetaDataCollector; import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
import org.apache.dubbo.admin.registry.metadata.impl.NoOpMetadataCollector; 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.URL;
import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.registry.Registry; import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.RegistryFactory; import org.apache.dubbo.registry.RegistryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -41,18 +43,25 @@ import java.util.Arrays; ...@@ -41,18 +43,25 @@ import java.util.Arrays;
public class ConfigCenter { public class ConfigCenter {
@Value("${dubbo.config-center:}")
//centers in dubbo 2.7
@Value("${admin.config-center:}")
private String configCenter; private String configCenter;
@Value("${dubbo.config-center.username:}")
private String username;
@Value("${dubbo.config-center.password:}")
private String password;
@Value("${dubbo.registry.address:}") @Value("${admin.registry.address:}")
private String registryAddress; private String registryAddress;
@Value("${dubbo.registry.group:}")
@Value("${admin.metadata.address:}")
private String metadataAddress;
@Value("${admin.registry.group:}")
private String 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 String globalConfigPath = "config/dubbo/dubbo.properties";
private static final Logger logger = LoggerFactory.getLogger(ConfigCenter.class); private static final Logger logger = LoggerFactory.getLogger(ConfigCenter.class);
...@@ -62,6 +71,7 @@ public class ConfigCenter { ...@@ -62,6 +71,7 @@ public class ConfigCenter {
private URL metadataUrl; private URL metadataUrl;
/* /*
* generate dynamic configuration client * generate dynamic configuration client
*/ */
...@@ -79,7 +89,8 @@ public class ConfigCenter { ...@@ -79,7 +89,8 @@ public class ConfigCenter {
if (StringUtils.isNotEmpty(config)) { if (StringUtils.isNotEmpty(config)) {
Arrays.stream(config.split("\n")).forEach( s -> { Arrays.stream(config.split("\n")).forEach( s -> {
if(s.startsWith(Constants.REGISTRY_ADDRESS)) { 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)) { } else if (s.startsWith(Constants.METADATA_ADDRESS)) {
metadataUrl = formUrl(s.split("=")[1].trim(), group, username, password); metadataUrl = formUrl(s.split("=")[1].trim(), group, username, password);
} }
...@@ -126,6 +137,11 @@ public class ConfigCenter { ...@@ -126,6 +137,11 @@ public class ConfigCenter {
@DependsOn("governanceConfiguration") @DependsOn("governanceConfiguration")
MetaDataCollector getMetadataCollector() { MetaDataCollector getMetadataCollector() {
MetaDataCollector metaDataCollector = new NoOpMetadataCollector(); MetaDataCollector metaDataCollector = new NoOpMetadataCollector();
if (metadataUrl == null) {
if (StringUtils.isNotEmpty(metadataAddress)) {
metadataUrl = formUrl(metadataAddress, group, username, password);
}
}
if (metadataUrl != null) { if (metadataUrl != null) {
metaDataCollector = ExtensionLoader.getExtensionLoader(MetaDataCollector.class).getExtension(metadataUrl.getProtocol()); metaDataCollector = ExtensionLoader.getExtensionLoader(MetaDataCollector.class).getExtension(metadataUrl.getProtocol());
metaDataCollector.setUrl(metadataUrl); metaDataCollector.setUrl(metadataUrl);
......
/*
* 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);
}
}
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.apache.dubbo.admin.controller; package org.apache.dubbo.admin.controller;
import com.ctrip.framework.apollo.core.enums.Env;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.apache.dubbo.admin.common.util.ConvertUtil; import org.apache.dubbo.admin.common.util.ConvertUtil;
import org.apache.dubbo.admin.model.domain.Consumer; import org.apache.dubbo.admin.model.domain.Consumer;
...@@ -26,7 +27,6 @@ import org.apache.dubbo.admin.model.dto.ServiceDetailDTO; ...@@ -26,7 +27,6 @@ import org.apache.dubbo.admin.model.dto.ServiceDetailDTO;
import org.apache.dubbo.admin.service.ConsumerService; import org.apache.dubbo.admin.service.ConsumerService;
import org.apache.dubbo.admin.service.ProviderService; import org.apache.dubbo.admin.service.ProviderService;
import org.apache.dubbo.admin.common.util.Constants; 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.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.identifier.MetadataIdentifier; import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -38,7 +38,7 @@ import java.util.regex.Pattern; ...@@ -38,7 +38,7 @@ import java.util.regex.Pattern;
@RestController @RestController
@RequestMapping("/api/{env}/service") @RequestMapping("/api/{env}")
public class ServiceController { public class ServiceController {
private final ProviderService providerService; private final ProviderService providerService;
...@@ -50,7 +50,7 @@ public class ServiceController { ...@@ -50,7 +50,7 @@ public class ServiceController {
this.consumerService = consumerService; this.consumerService = consumerService;
} }
@RequestMapping(method = RequestMethod.GET) @RequestMapping( value = "/service", method = RequestMethod.GET)
public Set<ServiceDTO> searchService(@RequestParam String pattern, public Set<ServiceDTO> searchService(@RequestParam String pattern,
@RequestParam String filter,@PathVariable String env) { @RequestParam String filter,@PathVariable String env) {
return providerService.getServiceDTOS(pattern, filter, env); return providerService.getServiceDTOS(pattern, filter, env);
...@@ -58,7 +58,7 @@ public class ServiceController { ...@@ -58,7 +58,7 @@ public class ServiceController {
@RequestMapping(value = "/{service}", method = RequestMethod.GET) @RequestMapping(value = "/service/{service}", method = RequestMethod.GET)
public ServiceDetailDTO serviceDetail(@PathVariable String service, @PathVariable String env) { public ServiceDetailDTO serviceDetail(@PathVariable String service, @PathVariable String env) {
service = service.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR); service = service.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
List<Provider> providers = providerService.findByService(service); List<Provider> providers = providerService.findByService(service);
...@@ -88,4 +88,14 @@ public class ServiceController { ...@@ -88,4 +88,14 @@ public class ServiceController {
serviceDetailDTO.setApplication(application); serviceDetailDTO.setApplication(application);
return serviceDetailDTO; 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();
}
} }
/*
* 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;
}
}
...@@ -40,4 +40,8 @@ public interface GovernanceConfiguration { ...@@ -40,4 +40,8 @@ public interface GovernanceConfiguration {
boolean deleteConfig(String group, String key); boolean deleteConfig(String group, String key);
String getPath(String key);
String getPath(String group, String key);
} }
...@@ -27,19 +27,19 @@ import org.springframework.beans.factory.annotation.Value; ...@@ -27,19 +27,19 @@ import org.springframework.beans.factory.annotation.Value;
@SPI("apollo") @SPI("apollo")
public class ApolloConfiguration implements GovernanceConfiguration { public class ApolloConfiguration implements GovernanceConfiguration {
@Value("${dubbo.apollo.token}") @Value("${admin.apollo.token}")
private String token; private String token;
@Value("${dubbo.apollo.cluster}") @Value("${admin.apollo.cluster}")
private String cluster; private String cluster;
@Value("${dubbo.apollo.namespace}") @Value("${admin.apollo.namespace}")
private String namespace; private String namespace;
@Value("${dubbo.apollo.env}") @Value("${admin.apollo.env}")
private String env; private String env;
@Value("${dubbo.apollo.appId}") @Value("${admin.apollo.appId}")
private String appId; private String appId;
private URL url; private URL url;
...@@ -109,4 +109,14 @@ public class ApolloConfiguration implements GovernanceConfiguration { ...@@ -109,4 +109,14 @@ public class ApolloConfiguration implements GovernanceConfiguration {
client.removeItem(appId, env, cluster, group, key, "admin"); client.removeItem(appId, env, cluster, group, key, "admin");
return true; return true;
} }
@Override
public String getPath(String key) {
return null;
}
@Override
public String getPath(String group, String key) {
return null;
}
} }
...@@ -66,4 +66,14 @@ public class NoOpConfiguration implements GovernanceConfiguration { ...@@ -66,4 +66,14 @@ public class NoOpConfiguration implements GovernanceConfiguration {
public boolean deleteConfig(String group, String key) { public boolean deleteConfig(String group, String key) {
return false; return false;
} }
@Override
public String getPath(String key) {
return null;
}
@Override
public String getPath(String group, String key) {
return null;
}
} }
...@@ -17,16 +17,16 @@ ...@@ -17,16 +17,16 @@
package org.apache.dubbo.admin.registry.config.impl; package org.apache.dubbo.admin.registry.config.impl;
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.common.util.Constants;
import org.apache.dubbo.admin.registry.config.GovernanceConfiguration; 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.Logger;
import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.URL;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
public class ZookeeperConfiguration implements GovernanceConfiguration { public class ZookeeperConfiguration implements GovernanceConfiguration {
private static final Logger logger = LoggerFactory.getLogger(ZookeeperConfiguration.class); private static final Logger logger = LoggerFactory.getLogger(ZookeeperConfiguration.class);
...@@ -46,10 +46,13 @@ public class ZookeeperConfiguration implements GovernanceConfiguration { ...@@ -46,10 +46,13 @@ public class ZookeeperConfiguration implements GovernanceConfiguration {
@Override @Override
public void init() { public void init() {
if (url == null) {
throw new IllegalStateException("server url is null, cannot init");
}
CuratorFrameworkFactory.Builder zkClientBuilder = CuratorFrameworkFactory.builder(). CuratorFrameworkFactory.Builder zkClientBuilder = CuratorFrameworkFactory.builder().
connectString(url.getAddress()). connectString(url.getAddress()).
retryPolicy(new ExponentialBackoffRetry(1000, 3)); 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 // add authorization
String auth = url.getUsername() + ":" + url.getPassword(); String auth = url.getUsername() + ":" + url.getPassword();
zkClientBuilder.authorization("digest", auth.getBytes()); zkClientBuilder.authorization("digest", auth.getBytes());
...@@ -80,6 +83,9 @@ public class ZookeeperConfiguration implements GovernanceConfiguration { ...@@ -80,6 +83,9 @@ public class ZookeeperConfiguration implements GovernanceConfiguration {
@Override @Override
public String setConfig(String group, String key, String value) { 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); String path = getNodePath(key, group);
try { try {
if (zkClient.checkExists().forPath(path) == null) { if (zkClient.checkExists().forPath(path) == null) {
...@@ -95,6 +101,9 @@ public class ZookeeperConfiguration implements GovernanceConfiguration { ...@@ -95,6 +101,9 @@ public class ZookeeperConfiguration implements GovernanceConfiguration {
@Override @Override
public String getConfig(String group, String key) { public String getConfig(String group, String key) {
if (key == null) {
throw new IllegalArgumentException("key cannot be null");
}
String path = getNodePath(key, group); String path = getNodePath(key, group);
try { try {
...@@ -110,16 +119,33 @@ public class ZookeeperConfiguration implements GovernanceConfiguration { ...@@ -110,16 +119,33 @@ public class ZookeeperConfiguration implements GovernanceConfiguration {
@Override @Override
public boolean deleteConfig(String group, String key) { public boolean deleteConfig(String group, String key) {
if (key == null) {
throw new IllegalArgumentException("key cannot be null");
}
String path = getNodePath(key, group); String path = getNodePath(key, group);
try { try {
zkClient.delete().forPath(path); zkClient.delete().forPath(path);
} catch (Exception e) { } catch (Exception e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
return false;
} }
return true; 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) { private String getNodePath(String path, String group) {
if (path == null) {
throw new IllegalArgumentException("path cannot be null");
}
return toRootDir(group) + path; return toRootDir(group) + path;
} }
......
/*
* 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);
}
...@@ -52,7 +52,7 @@ public interface ProviderService { ...@@ -52,7 +52,7 @@ public interface ProviderService {
* *
* @return list of all provider's service name * @return list of all provider's service name
*/ */
List<String> findServices(); Set<String> findServices();
String findServiceVersion(String serviceName, String application); String findServiceVersion(String serviceName, String application);
...@@ -88,7 +88,7 @@ public interface ProviderService { ...@@ -88,7 +88,7 @@ public interface ProviderService {
List<String> findServicesByAddress(String providerAddress); List<String> findServicesByAddress(String providerAddress);
List<String> findApplications(); Set<String> findApplications();
/** /**
* Get provider list with specific application name. * Get provider list with specific application name.
...@@ -117,4 +117,4 @@ public interface ProviderService { ...@@ -117,4 +117,4 @@ public interface ProviderService {
*/ */
Set<ServiceDTO> getServiceDTOS(String pattern, String filter, String env); Set<ServiceDTO> getServiceDTOS(String pattern, String filter, String env);
} }
\ No newline at end of file
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
*/ */
package org.apache.dubbo.admin.service; 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.admin.common.util.Tool;
import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL; import org.apache.dubbo.common.URL;
...@@ -134,7 +134,7 @@ public class RegistryServerSync implements InitializingBean, DisposableBean, Not ...@@ -134,7 +134,7 @@ public class RegistryServerSync implements InitializingBean, DisposableBean, Not
if (URL_IDS_MAPPER.containsKey(url.toFullString())) { if (URL_IDS_MAPPER.containsKey(url.toFullString())) {
ids.put(URL_IDS_MAPPER.get(url.toFullString()), url); ids.put(URL_IDS_MAPPER.get(url.toFullString()), url);
} else { } else {
String md5 = MD5Util.MD5_16bit(url.toFullString()); String md5 = CoderUtil.MD5_16bit(url.toFullString());
ids.put(md5, url); ids.put(md5, url);
URL_IDS_MAPPER.putIfAbsent(url.toFullString(), md5); URL_IDS_MAPPER.putIfAbsent(url.toFullString(), md5);
} }
......
/*
* 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;
}
}
...@@ -253,8 +253,8 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ ...@@ -253,8 +253,8 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
} }
@Override @Override
public List<String> findServices() { public Set<String> findServices() {
List<String> ret = new ArrayList<String>(); Set<String> ret = new HashSet<>();
ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
if (providerUrls != null){ if (providerUrls != null){
ret.addAll(providerUrls.keySet()); ret.addAll(providerUrls.keySet());
...@@ -413,8 +413,8 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ ...@@ -413,8 +413,8 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
} }
@Override @Override
public List<String> findApplications() { public Set<String> findApplications() {
List<String> ret = new ArrayList<String>(); Set<String> ret = new HashSet<>();
ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
if (providerUrls == null){ if (providerUrls == null){
return ret; return ret;
...@@ -568,7 +568,7 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ ...@@ -568,7 +568,7 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
} }
} else { } else {
// filter with fuzzy search // filter with fuzzy search
List<String> candidates = Collections.emptyList(); Set<String> candidates = Collections.emptySet();
if (Constants.SERVICE.equals(pattern)) { if (Constants.SERVICE.equals(pattern)) {
candidates = findServices(); candidates = findServices();
} else if (Constants.APPLICATION.equals(pattern)) { } else if (Constants.APPLICATION.equals(pattern)) {
......
...@@ -15,13 +15,16 @@ ...@@ -15,13 +15,16 @@
# limitations under the License. # limitations under the License.
# #
dubbo.config-center.username=username # centers in dubbo2.7
dubbo.config-center.password=password admin.registry.address=zookeeper://127.0.0.1:2181
dubbo.config-center=zookeeper://127.0.0.1:2181 admin.config-center=zookeeper://127.0.0.1:2181
dubbo.registry.group=dubbo admin.metadata.address=zookeeper://127.0.0.1:2181
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.apollo.token=e16e5cd903fd0c97a116c873b448544b9d086de9
dubbo.apollo.appId=test
dubbo.apollo.env=dev admin.registry.group=dubbo
dubbo.apollo.cluster=default admin.apollo.token=e16e5cd903fd0c97a116c873b448544b9d086de9
dubbo.apollo.namespace=dubbo admin.apollo.appId=test
admin.apollo.env=dev
admin.apollo.cluster=default
admin.apollo.namespace=dubbo
/*
* 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();
}
}
...@@ -32,8 +32,8 @@ const Menu = [ ...@@ -32,8 +32,8 @@ const Menu = [
}, },
{ title: 'serviceTest', path: '/test', icon: 'code', badge: 'feature' }, { title: 'serviceTest', path: '/test', icon: 'code', badge: 'feature' },
{ title: 'serviceMock', path: '/mock', icon: 'build', 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 export default Menu
<!--
- 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>
...@@ -312,18 +312,19 @@ ...@@ -312,18 +312,19 @@
pattern = 'service' pattern = 'service'
this.search(this.filter, pattern, true) this.search(this.filter, pattern, true)
} }
this.$axios.get('/service', { this.$axios.get('/services')
params: { .then(response => {
pattern: 'service', if (response.status === 200) {
filter: '*' vm.serviceItem = response.data
} }
}).then(response => { })
let length = response.data.length
for (let i = 0; i < length; i++) { this.$axios.get('/applications')
vm.serviceItem.push(response.data[i].service) .then(response => {
vm.appItem.push(response.data[i].appName) if (response.status === 200) {
} vm.appItem = response.data
}) }
})
} }
} }
......
...@@ -78,14 +78,14 @@ ...@@ -78,14 +78,14 @@
</v-card> </v-card>
</v-dialog> </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>
<v-card-title class="headline">{{$t(this.warnTitle)}}</v-card-title> <v-card-title class="headline">{{$t(this.warn.title)}}</v-card-title>
<v-card-text >{{this.warnText}}</v-card-text> <v-card-text >{{this.warn.text}}</v-card-text>
<v-card-actions> <v-card-actions>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn flat @click.native="closeWarn">CANCLE</v-btn> <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-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>
...@@ -110,12 +110,14 @@ ...@@ -110,12 +110,14 @@
pattern: 'Service', pattern: 'Service',
filter: '', filter: '',
dialog: false, dialog: false,
warn: false,
updateId: '', updateId: '',
application: '', application: '',
warnTitle: '', warn: {
warnText: '', display: false,
warnStatus: {}, title: '',
text: '',
status: {}
},
height: 0, height: 0,
operations: operations, operations: operations,
tagRoutingRules: [ tagRoutingRules: [
...@@ -179,14 +181,14 @@ ...@@ -179,14 +181,14 @@
this.dialog = true this.dialog = true
}, },
openWarn: function (title, text) { openWarn: function (title, text) {
this.warnTitle = title this.warn.title = title
this.warnText = text this.warn.text = text
this.warn = true this.warn.display = true
}, },
closeWarn: function () { closeWarn: function () {
this.warnTitle = '' this.warn.title = ''
this.warnText = '' this.warn.text = ''
this.warn = false this.warn.display = false
}, },
saveItem: function () { saveItem: function () {
let rule = yaml.safeLoad(this.ruleText) let rule = yaml.safeLoad(this.ruleText)
...@@ -248,18 +250,18 @@ ...@@ -248,18 +250,18 @@
break break
case 'block': case 'block':
this.openWarn(' Are you sure to block Tag Rule', 'application: ' + item.application) this.openWarn(' Are you sure to block Tag Rule', 'application: ' + item.application)
this.warnStatus.operation = 'disable' this.warn.status.operation = 'disable'
this.warnStatus.id = itemId this.warn.status.id = itemId
break break
case 'check_circle_outline': case 'check_circle_outline':
this.openWarn(' Are you sure to enable Tag Rule', 'application: ' + item.application) this.openWarn(' Are you sure to enable Tag Rule', 'application: ' + item.application)
this.warnStatus.operation = 'enable' this.warn.status.operation = 'enable'
this.warnStatus.id = itemId this.warn.status.id = itemId
break break
case 'delete': case 'delete':
this.openWarn(' Are you sure to Delete Tag Rule', 'application: ' + item.application) this.openWarn(' Are you sure to Delete Tag Rule', 'application: ' + item.application)
this.warnStatus.operation = 'delete' this.warn.status.operation = 'delete'
this.warnStatus.id = itemId this.warn.status.id = itemId
} }
}, },
handleBalance: function (tagRoute, readonly) { handleBalance: function (tagRoute, readonly) {
...@@ -284,7 +286,7 @@ ...@@ -284,7 +286,7 @@
this.$axios.delete('/rules/route/tag/' + id) this.$axios.delete('/rules/route/tag/' + id)
.then(response => { .then(response => {
if (response.status === 200) { if (response.status === 200) {
this.warn = false this.warn.display = false
this.search(this.filter, false) this.search(this.filter, false)
this.$notify.success('Delete success') this.$notify.success('Delete success')
} }
...@@ -293,7 +295,7 @@ ...@@ -293,7 +295,7 @@
this.$axios.put('/rules/route/tag/disable/' + id) this.$axios.put('/rules/route/tag/disable/' + id)
.then(response => { .then(response => {
if (response.status === 200) { if (response.status === 200) {
this.warn = false this.warn.display = false
this.search(this.filter, false) this.search(this.filter, false)
this.$notify.success('Disable success') this.$notify.success('Disable success')
} }
...@@ -302,7 +304,7 @@ ...@@ -302,7 +304,7 @@
this.$axios.put('/rules/route/tag/enable/' + id) this.$axios.put('/rules/route/tag/enable/' + id)
.then(response => { .then(response => {
if (response.status === 200) { if (response.status === 200) {
this.warn = false this.warn.display = false
this.search(this.filter, false) this.search(this.filter, false)
this.$notify.success('Enable success') this.$notify.success('Enable success')
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
<v-layout row wrap > <v-layout row wrap >
<v-text-field <v-text-field
:label="label" clearable :label="label" clearable
:hint="hint"
v-bind:value="value" v-bind:value="value"
v-on:input="$emit('input', $event)"></v-text-field> v-on:input="$emit('input', $event)"></v-text-field>
<v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn> <v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn>
...@@ -41,6 +42,10 @@ ...@@ -41,6 +42,10 @@
label: { label: {
type: String, type: String,
default: '' default: ''
},
hint: {
type: String,
default: ''
} }
}, },
data: () => ({ data: () => ({
......
...@@ -114,5 +114,13 @@ export default { ...@@ -114,5 +114,13 @@ export default {
rowsPerPageText: 'Rows per page:' rowsPerPageText: 'Rows per page:'
}, },
noDataText: 'No data available' 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"
} }
...@@ -114,5 +114,13 @@ export default { ...@@ -114,5 +114,13 @@ export default {
rowsPerPageText: '每页行数:' rowsPerPageText: '每页行数:'
}, },
noDataText: '无可用数据' noDataText: '无可用数据'
} },
configManage: '配置管理',
configCenterAddress: '配置中心地址',
searchDubboConfig: '搜索Dubbo配置',
createNewDubboConfig: '新建Dubbo配置',
scope: '范围',
name: '名称',
warnDeleteConfig: ' 是否要删除Dubbo配置: ',
configNameHint: '配置所属的应用名, global 表示全局配置'
} }
...@@ -29,6 +29,7 @@ import Overrides from '@/components/governance/Overrides' ...@@ -29,6 +29,7 @@ import Overrides from '@/components/governance/Overrides'
import ServiceTest from '@/components/test/ServiceTest' import ServiceTest from '@/components/test/ServiceTest'
import ServiceMock from '@/components/test/ServiceMock' import ServiceMock from '@/components/test/ServiceMock'
import ServiceMetrics from '@/components/metrics/ServiceMetrics' import ServiceMetrics from '@/components/metrics/ServiceMetrics'
import Management from '@/components/Management'
Vue.use(Router) Vue.use(Router)
...@@ -92,6 +93,11 @@ export default new Router({ ...@@ -92,6 +93,11 @@ export default new Router({
path: '/metrics', path: '/metrics',
name: 'ServiceMetrics', name: 'ServiceMetrics',
component: ServiceMetrics component: ServiceMetrics
},
{
path: '/management',
name: 'Management',
component: Management
} }
] ]
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
<commons-lang3-version>3.7</commons-lang3-version> <commons-lang3-version>3.7</commons-lang3-version>
<dubbo-version>2.7.0-SNAPSHOT</dubbo-version> <dubbo-version>2.7.0-SNAPSHOT</dubbo-version>
<curator-version>2.12.0</curator-version> <curator-version>2.12.0</curator-version>
<curator-test-version>2.12.0</curator-test-version>
<fastjson-version>1.2.46</fastjson-version> <fastjson-version>1.2.46</fastjson-version>
<springfox-swagger-version>2.9.2</springfox-swagger-version> <springfox-swagger-version>2.9.2</springfox-swagger-version>
<netty-version>4.1.30.Final</netty-version> <netty-version>4.1.30.Final</netty-version>
...@@ -102,6 +103,13 @@ ...@@ -102,6 +103,13 @@
<artifactId>curator-framework</artifactId> <artifactId>curator-framework</artifactId>
<version>${curator-version}</version> <version>${curator-version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-test</artifactId>
<version>${curator-test-version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.curator</groupId> <groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId> <artifactId>curator-recipes</artifactId>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册