diff --git a/address/pom.xml b/address/pom.xml new file mode 100644 index 00000000000..5621eb32134 --- /dev/null +++ b/address/pom.xml @@ -0,0 +1,123 @@ + + + + + nacos-all + com.alibaba.nacos + 1.1.0 + + + 4.0.0 + nacos-address + jar + + nacos-address ${project.version} + http://maven.apache.org + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + test + + + org.apache.commons + commons-lang3 + + + + ${project.groupId} + nacos-naming + + + com.alibaba.nacos + nacos-cmdb + + + + + org.mockito + mockito-all + 1.10.19 + test + + + org.hamcrest + hamcrest-all + 1.3 + test + + + + + + + src/main/resources + + + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.4 + + + + + + + release-address + + nacos-address + + + maven-jar-plugin + + + + true + true + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.alibaba.nacos.address.AddressServer + + + + + repackage + + + + + + + + + diff --git a/address/src/main/java/com/alibaba/nacos/address/AddressServer.java b/address/src/main/java/com/alibaba/nacos/address/AddressServer.java new file mode 100644 index 00000000000..a963cda64f0 --- /dev/null +++ b/address/src/main/java/com/alibaba/nacos/address/AddressServer.java @@ -0,0 +1,33 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * support address server. + * + * @author nacos + * @since 1.1.0 + */ +@SpringBootApplication(scanBasePackages = "com.alibaba.nacos") +public class AddressServer { + public static void main(String[] args) { + + SpringApplication.run(AddressServer.class, args); + } +} diff --git a/address/src/main/java/com/alibaba/nacos/address/component/AddressServerGeneratorManager.java b/address/src/main/java/com/alibaba/nacos/address/component/AddressServerGeneratorManager.java new file mode 100644 index 00000000000..0a35471eab6 --- /dev/null +++ b/address/src/main/java/com/alibaba/nacos/address/component/AddressServerGeneratorManager.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address.component; + +import com.alibaba.nacos.address.constant.AddressServerConstants; +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.naming.core.Instance; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * will generator some result by the input parameter. + * + * @author pbting + * @date 2019-07-01 8:53 PM + * @since 1.1.0 + */ +@Component +public class AddressServerGeneratorManager { + + public String generateProductName(String name) { + + if (StringUtils.isBlank(name) || AddressServerConstants.DEFAULT_PRODUCT.equals(name)) { + + return AddressServerConstants.ALIWARE_NACOS_DEFAULT_PRODUCT_NAME; + } + + return String.format(AddressServerConstants.ALIWARE_NACOS_PRODUCT_DOM_TEMPLATE, name); + } + + /** + * Note: if the parameter inputted is empty then will return the empty list. + * + * @param serviceName + * @param clusterName + * @param ipArray + * @return + */ + public List generateInstancesByIps(String serviceName, String rawProductName, String clusterName, String[] ipArray) { + if (StringUtils.isEmpty(serviceName) + || StringUtils.isEmpty(clusterName) + || ipArray == null || ipArray.length == 0) { + return Collections.emptyList(); + } + + List instanceList = new ArrayList<>(ipArray.length); + for (String ip : ipArray) { + String[] ipAndPort = generateIpAndPort(ip); + Instance instance = new Instance(); + instance.setIp(ipAndPort[0]); + instance.setPort(Integer.valueOf(ipAndPort[1])); + instance.setClusterName(clusterName); + instance.setServiceName(serviceName); + instance.setTenant(Constants.DEFAULT_NAMESPACE_ID); + instance.setApp(rawProductName); + instance.setEphemeral(false); + instanceList.add(instance); + } + + return instanceList; + } + + public String[] generateIpAndPort(String ip) { + + int index = ip.indexOf(AddressServerConstants.IP_PORT_SEPARATOR); + if (index != -1) { + + return new String[]{ip.substring(0, index), ip.substring(index + 1)}; + } + + return new String[]{ip, String.valueOf(AddressServerConstants.DEFAULT_SERVER_PORT)}; + } + + /** + * @param instanceList a instance set will generate string response to client. + * @return the result of response to client + */ + public String generateResponseIps(List instanceList) { + + StringBuilder ips = new StringBuilder(); + instanceList.forEach(instance -> { + ips.append(instance.getIp() + ":" + instance.getPort()); + ips.append("\n"); + }); + + return ips.toString(); + } + + /** + * @param rawServiceName the raw service name will not contains the {@Constans.DEFAULT_GROUP} + * @return the nacos service name + */ + public String generateNacosServiceName(String rawServiceName) { + + if (rawServiceName.indexOf(Constants.DEFAULT_GROUP) != -1) { + return rawServiceName; + } + + return Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + rawServiceName; + } +} diff --git a/address/src/main/java/com/alibaba/nacos/address/component/AddressServerManager.java b/address/src/main/java/com/alibaba/nacos/address/component/AddressServerManager.java new file mode 100644 index 00000000000..c3a6d01a804 --- /dev/null +++ b/address/src/main/java/com/alibaba/nacos/address/component/AddressServerManager.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address.component; + +import com.alibaba.nacos.address.constant.AddressServerConstants; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +/** + * This class holds the IP list of the CAI's address service. + * + * @author deshao + * @date 2016/4/28 20:58 + * @since 1.1.0 + */ +@Component +public class AddressServerManager { + + public String getRawProductName(String name) { + + if (StringUtils.isBlank(name) || AddressServerConstants.DEFAULT_PRODUCT.equals(name)) { + + return AddressServerConstants.DEFAULT_PRODUCT; + } + + return name; + } + + /** + *

+ * if the name is empty then return the default {@UtilAndCommons#DEFAULT_CLUSTER_NAME}, + *

+ * or return the source name by input + * + * @param name + * @return + */ + public String getDefaultClusterNameIfEmpty(String name) { + + if (StringUtils.isEmpty(name) || AddressServerConstants.DEFAULT_GET_CLUSTER.equals(name)) { + return AddressServerConstants.DEFAULT_GET_CLUSTER; + } + + return name; + } + + public String getRawClusterName(String name) { + + return getDefaultClusterNameIfEmpty(name); + } + + /** + * @param ips multi ip will separator by the ',' + * @return + */ + public String[] splitIps(String ips) { + + if (StringUtils.isBlank(ips)) { + + return new String[0]; + } + + return ips.split(AddressServerConstants.MULTI_IPS_SEPARATOR); + } +} diff --git a/address/src/main/java/com/alibaba/nacos/address/constant/AddressServerConstants.java b/address/src/main/java/com/alibaba/nacos/address/constant/AddressServerConstants.java new file mode 100644 index 00000000000..c60881b92ec --- /dev/null +++ b/address/src/main/java/com/alibaba/nacos/address/constant/AddressServerConstants.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address.constant; + +import com.alibaba.nacos.naming.misc.UtilsAndCommons; + +/** + * Uniform constant parameter naming for address servers and default values ​​for related parameters + * + * @author pbting + * @date 2019-06-17 7:23 PM + * @since 1.1.0 + */ +public interface AddressServerConstants { + + + /** + * the default server port when create the Instance object. + */ + int DEFAULT_SERVER_PORT = 8848; + + /** + * when post ips is not given the product,then use the default. + */ + String DEFAULT_PRODUCT = "nacos"; + + /** + * the separator between ip and port. + */ + String IP_PORT_SEPARATOR = ":"; + + /** + * the separator for {@Service#name} between raw service name and group + */ + String GROUP_SERVICE_NAME_SEP = "@@"; + + /** + * when post ips is not given the cluster,then use the default. + */ + String DEFAULT_GET_CLUSTER = "serverlist"; + + /** + * post multi ip will use the "," to separator + */ + String MULTI_IPS_SEPARATOR = ","; + + /** + * the default product name when deploy nacos with naming and config + */ + String ALIWARE_NACOS_DEFAULT_PRODUCT_NAME = "nacos.as.default"; + + /** + * when the config and naming will separate deploy,then must specify product name by the client。 + */ + String ALIWARE_NACOS_PRODUCT_DOM_TEMPLATE = "nacos.as.%s"; + + /** + * the url for address server prefix + */ + String ADDRESS_SERVER_REQUEST_URL = + UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.NACOS_SERVER_VERSION + "/as"; + +} diff --git a/address/src/main/java/com/alibaba/nacos/address/controller/AddressServerClusterController.java b/address/src/main/java/com/alibaba/nacos/address/controller/AddressServerClusterController.java new file mode 100644 index 00000000000..347b792d811 --- /dev/null +++ b/address/src/main/java/com/alibaba/nacos/address/controller/AddressServerClusterController.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address.controller; + +import com.alibaba.nacos.address.component.AddressServerGeneratorManager; +import com.alibaba.nacos.address.component.AddressServerManager; +import com.alibaba.nacos.address.constant.AddressServerConstants; +import com.alibaba.nacos.address.misc.Loggers; +import com.alibaba.nacos.address.util.AddressServerParamCheckUtil; +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker; +import com.alibaba.nacos.naming.core.Cluster; +import com.alibaba.nacos.naming.core.Instance; +import com.alibaba.nacos.naming.core.Service; +import com.alibaba.nacos.naming.core.ServiceManager; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @author pbting + * @date 2019-06-10 9:59 AM + * @since 1.1.0 + */ +@RestController +@RequestMapping({AddressServerConstants.ADDRESS_SERVER_REQUEST_URL + "/nodes"}) +public class AddressServerClusterController { + + @Autowired + private ServiceManager serviceManager; + + @Autowired + private AddressServerManager addressServerManager; + + @Autowired + private AddressServerGeneratorManager addressServerGeneratorManager; + + /** + * @param product Ip list of products to be associated + * @param cluster Ip list of product cluster to be associated + * @param ips will post ip list. + * @return + */ + @RequestMapping(value = "", method = RequestMethod.POST) + public ResponseEntity postCluster(@RequestParam(required = false) String product, + @RequestParam(required = false) String cluster, + @RequestParam(name = "ips") String ips) { + + //1. prepare the storage name for product and cluster + String productName = addressServerGeneratorManager.generateProductName(product); + String clusterName = addressServerManager.getDefaultClusterNameIfEmpty(cluster); + + //2. prepare the response name for product and cluster to client + String rawProductName = addressServerManager.getRawProductName(product); + String rawClusterName = addressServerManager.getRawClusterName(cluster); + Loggers.addressLogger.info("put cluster node,the cluster name is " + cluster + "; the product name=" + product + "; the ip list=" + ips); + ResponseEntity responseEntity; + try { + String serviceName = addressServerGeneratorManager.generateNacosServiceName(productName); + + Cluster clusterObj = new Cluster(); + clusterObj.setName(clusterName); + clusterObj.setHealthChecker(new AbstractHealthChecker.None()); + serviceManager.createServiceIfAbsent(Constants.DEFAULT_NAMESPACE_ID, serviceName, false, clusterObj); + String[] ipArray = addressServerManager.splitIps(ips); + String checkResult = AddressServerParamCheckUtil.checkIps(ipArray); + if (AddressServerParamCheckUtil.CHECK_OK.equals(checkResult)) { + List instanceList = addressServerGeneratorManager.generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray); + for (Instance instance : instanceList) { + serviceManager.registerInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, instance); + } + responseEntity = ResponseEntity.ok("product=" + rawProductName + ",cluster=" + rawClusterName + "; put success with size=" + instanceList.size()); + } else { + responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(checkResult); + } + } catch (Exception e) { + responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); + } + + return responseEntity; + } + + /** + * @param product Ip list of products to be associated + * @param cluster Ip list of product cluster to be associated + * @param ips will delete ips. + * @return + */ + @RequestMapping(value = "", method = RequestMethod.DELETE) + public ResponseEntity deleteCluster(@RequestParam(required = false) String product, + @RequestParam(required = false) String cluster, + @RequestParam String ips) { + //1. prepare the storage name for product and cluster + String productName = addressServerGeneratorManager.generateProductName(product); + String clusterName = addressServerManager.getDefaultClusterNameIfEmpty(cluster); + + //2. prepare the response name for product and cluster to client + String rawProductName = addressServerManager.getRawProductName(product); + String rawClusterName = addressServerManager.getRawClusterName(cluster); + ResponseEntity responseEntity = ResponseEntity.status(HttpStatus.OK).body("product=" + rawProductName + ", cluster=" + rawClusterName + " delete success."); + try { + + String serviceName = addressServerGeneratorManager.generateNacosServiceName(productName); + Service service = serviceManager.getService(Constants.DEFAULT_NAMESPACE_ID, serviceName); + + if (service == null) { + responseEntity = ResponseEntity.status(HttpStatus.NOT_FOUND).body("product=" + rawProductName + " not found."); + } else { + + if (StringUtils.isBlank(ips)) { + // delete all ips from the cluster + responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body("ips must not be empty."); + } else { + // delete specified ip list + String[] ipArray = addressServerManager.splitIps(ips); + String checkResult = AddressServerParamCheckUtil.checkIps(ipArray); + if (AddressServerParamCheckUtil.CHECK_OK.equals(checkResult)) { + List instanceList = addressServerGeneratorManager.generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray); + serviceManager.removeInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, false, instanceList.toArray(new Instance[instanceList.size()])); + } else { + responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(checkResult); + } + } + } + } catch (Exception e) { + + responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getCause()); + } + + return responseEntity; + } + +} diff --git a/address/src/main/java/com/alibaba/nacos/address/controller/ServerListController.java b/address/src/main/java/com/alibaba/nacos/address/controller/ServerListController.java new file mode 100644 index 00000000000..263fc897aca --- /dev/null +++ b/address/src/main/java/com/alibaba/nacos/address/controller/ServerListController.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address.controller; + +import com.alibaba.nacos.address.component.AddressServerGeneratorManager; +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.naming.core.Cluster; +import com.alibaba.nacos.naming.core.Service; +import com.alibaba.nacos.naming.core.ServiceManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author pbting + * @date 2019-06-18 5:04 PM + * @since 1.1.0 + */ +@RestController +public class ServerListController { + + @Autowired + private ServiceManager serviceManager; + + @Autowired + private AddressServerGeneratorManager addressServerBuilderManager; + + /** + * @param product will get Ip list of that products to be associated + * @param cluster will get Ip list of that product cluster to be associated + * @return + */ + @RequestMapping(value = "/{product}/{cluster}", method = RequestMethod.GET) + public ResponseEntity getCluster(@PathVariable String product, + @PathVariable String cluster) { + + String productName = addressServerBuilderManager.generateProductName(product); + String serviceName = addressServerBuilderManager.generateNacosServiceName(productName); + Service service = serviceManager.getService(Constants.DEFAULT_NAMESPACE_ID, serviceName); + if (service == null) { + + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("product=" + product + " not found."); + } + + if (!service.getClusterMap().containsKey(cluster)) { + + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("product=" + product + ",cluster=" + cluster + " not found."); + } + + Cluster clusterObj = service.getClusterMap().get(cluster); + return ResponseEntity.status(HttpStatus.OK).body(addressServerBuilderManager.generateResponseIps(clusterObj.allIPs(false))); + } +} diff --git a/address/src/main/java/com/alibaba/nacos/address/misc/Loggers.java b/address/src/main/java/com/alibaba/nacos/address/misc/Loggers.java new file mode 100644 index 00000000000..dd707de100b --- /dev/null +++ b/address/src/main/java/com/alibaba/nacos/address/misc/Loggers.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address.misc; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author pbting + * @date 2019-07-04 4:34 PM + */ +public class Loggers { + + public static final Logger addressLogger = LoggerFactory.getLogger("com.alibaba.nacos.address.main"); +} diff --git a/address/src/main/java/com/alibaba/nacos/address/util/AddressServerParamCheckUtil.java b/address/src/main/java/com/alibaba/nacos/address/util/AddressServerParamCheckUtil.java new file mode 100644 index 00000000000..ec4e991d31b --- /dev/null +++ b/address/src/main/java/com/alibaba/nacos/address/util/AddressServerParamCheckUtil.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Provides a unified tool class for address server parameter verification + * + * @author pbting + * @date 2019-06-19 11:19 AM + * @since 1.1.0 + */ +public class AddressServerParamCheckUtil { + + public static final String CHECK_OK = "ok"; + + public static final String ILLEGAL_IP_PREFIX = "illegal ip: "; + + private static final String IP_REGEX = "(2(5[0-5]{1}|[0-4]\\d{1})|[0-1]?\\d{1,2})(\\.(2(5[0-5]{1}|[0-4]\\d{1})|[0-1]?\\d{1,2})){3}"; + + private static final Pattern IP_PATTERN = Pattern.compile(IP_REGEX); + + public static String checkIps(String... ips) { + + if (ips == null || ips.length == 0) { + + return CHECK_OK; + } + // illegal response + StringBuilder illegalResponse = new StringBuilder(); + for (String ip : ips) { + Matcher matcher = IP_PATTERN.matcher(ip); + if (matcher.matches()) { + continue; + } + illegalResponse.append(ip + ","); + } + + if (illegalResponse.length() == 0) { + return CHECK_OK; + } + + return ILLEGAL_IP_PREFIX + illegalResponse.substring(0, illegalResponse.length() - 1); + } +} diff --git a/address/src/main/resources/META-INF/logback/nacos-included.xml b/address/src/main/resources/META-INF/logback/nacos-included.xml new file mode 100644 index 00000000000..44f88e2c072 --- /dev/null +++ b/address/src/main/resources/META-INF/logback/nacos-included.xml @@ -0,0 +1,29 @@ + + + + + + + + ${LOG_HOME}/nacos-address.log + true + + ${LOG_HOME}/nacos-address.log.%d{yyyy-MM-dd}.%i + 2GB + 15 + 7GB + true + + + %date %level %msg%n%n + UTF-8 + + + + + + + + + diff --git a/address/src/main/resources/META-INF/nacos-default.properties b/address/src/main/resources/META-INF/nacos-default.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/address/src/main/resources/application.properties b/address/src/main/resources/application.properties new file mode 100644 index 00000000000..8a6c9ff9b65 --- /dev/null +++ b/address/src/main/resources/application.properties @@ -0,0 +1,2 @@ +server.port=8080 +server.servlet.context-path=/ diff --git a/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java b/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java new file mode 100644 index 00000000000..b549536aab9 --- /dev/null +++ b/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address; + +import org.junit.Test; + +import java.util.HashMap; + +/** + * @author pbting + * @date 2019-06-18 2:37 PM + */ +public class AddressServerControllerTests { + + private static final String PRODUCT_NACOS = "nacos"; + private static final String PRODUCT_CONFIG = "config"; + private static final String PRODUCT_NAMING = "naming"; + private static final String DEFAULT_URL_CLUSTER = "serverlist"; + + private static final String GET_SERVERLIST_URL_FORMART = "http://127.0.0.1:8080/%s/%s"; + + //-----------------product=nacos,cluster=DEFAULT -------------------// + + /** + * test the default product and cluster + */ + @Test + public void postCluster() { + + String ips = "127.0.0.100,127.0.0.102,127.0.0.104"; + HashMap params = new HashMap<>(); + params.put("ips", ips); + String response = SimpleHttpTestUtils.doPost("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + @Test + public void getCluster() { + + String getUrl = String.format(GET_SERVERLIST_URL_FORMART, PRODUCT_NACOS, DEFAULT_URL_CLUSTER); + String response = SimpleHttpTestUtils.doGet(getUrl, new HashMap<>(), "UTF-8"); + System.err.println(response); + } + + @Test + public void deleteCluster() { + HashMap deleteIp = new HashMap<>(); + deleteIp.put("ips", "127.0.0.104"); + String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", deleteIp, "UTF-8"); + System.err.println(response); + } + + @Test + public void deleteClusterWithSpecIp() { + HashMap params = new HashMap<>(); + params.put("ips", "127.0.0.103"); + String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + @Test + public void putCluster() { + + String ips = "127.0.0.114"; + HashMap params = new HashMap<>(); + params.put("ips", ips); + String response = SimpleHttpTestUtils.doPut("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + //-----------------product=config,cluster=cluster01 -------------------// + + /** + * test with product + */ + + @Test + public void postClusterWithProduct() { + + String ips = "127.0.0.101,127.0.0.102,127.0.0.103"; + HashMap params = new HashMap<>(); + params.put("ips", ips); + params.put("product", PRODUCT_CONFIG); + String response = SimpleHttpTestUtils.doPost("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + @Test + public void getClusterWithProduct() { + HashMap params = new HashMap<>(); + String getUrl = String.format(GET_SERVERLIST_URL_FORMART, PRODUCT_CONFIG, DEFAULT_URL_CLUSTER); + String response = SimpleHttpTestUtils.doGet(getUrl, params, "UTF-8"); + System.err.println(response); + } + + @Test + public void deleteClusterWithProduct() { + HashMap params = new HashMap<>(); + params.put("product", PRODUCT_CONFIG); + String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + @Test + public void deleteClusterWithProductAndIp() { + HashMap params = new HashMap<>(); + params.put("product", PRODUCT_CONFIG); + params.put("ips", "127.0.0.196"); + String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + @Test + public void putClusterWithProduct() { + + String ips = "127.0.0.196"; + HashMap params = new HashMap<>(); + params.put("ips", ips); + params.put("product", PRODUCT_CONFIG); + String response = SimpleHttpTestUtils.doPut("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + + //-----------------product=naming,cluster=cluster01 -------------------// + + /** + * test with product and cluster + */ + @Test + public void postClusterWithProductAndCluster() { + + String ips = "127.0.0.100,127.0.0.200,127.0.0.31"; + HashMap params = new HashMap<>(); + params.put("ips", ips); + params.put("product", PRODUCT_NAMING); + params.put("cluster", "cluster01"); + String response = SimpleHttpTestUtils.doPost("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + @Test + public void getClusterWithProductAndCluster() { + HashMap params = new HashMap<>(); + String getUrl = String.format(GET_SERVERLIST_URL_FORMART, PRODUCT_NAMING, "cluster01"); + String response = SimpleHttpTestUtils.doGet(getUrl, params, "UTF-8"); + System.err.println(response); + } + + @Test + public void deleteClusterWithProductAndCluster() { + HashMap params = new HashMap<>(); + params.put("product", PRODUCT_NAMING); + params.put("cluster", "cluster01"); + String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + @Test + public void deleteClusterWithProductAndClusterAndIp() { + HashMap params = new HashMap<>(); + params.put("product", PRODUCT_NAMING); + params.put("cluster", "cluster01"); + params.put("ips", "127.0.0.200"); + String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } + + @Test + public void putClusterWithProductAndCluster() { + + String ips = "127.0.0.171"; + HashMap params = new HashMap<>(); + params.put("ips", ips); + params.put("product", PRODUCT_NAMING); + params.put("cluster", "cluster01"); + String response = SimpleHttpTestUtils.doPut("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8"); + System.err.println(response); + } +} diff --git a/address/src/test/java/com/alibaba/nacos/address/ParamCheckUtilTests.java b/address/src/test/java/com/alibaba/nacos/address/ParamCheckUtilTests.java new file mode 100644 index 00000000000..395bfcac429 --- /dev/null +++ b/address/src/test/java/com/alibaba/nacos/address/ParamCheckUtilTests.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address; + +import com.alibaba.nacos.address.util.AddressServerParamCheckUtil; +import org.junit.Test; + +/** + * @author pbting + * @date 2019-06-19 11:31 AM + */ +public class ParamCheckUtilTests { + + @Test + public void checkIps() { + String[] ips = {"127.0.0.1"}; + System.out.println(AddressServerParamCheckUtil.checkIps(ips)); + + String[] illlegalIps = {"127.100.19", "127.0.0.1"}; + System.err.println(AddressServerParamCheckUtil.checkIps(illlegalIps)); + } +} diff --git a/address/src/test/java/com/alibaba/nacos/address/SimpleHttpTestUtils.java b/address/src/test/java/com/alibaba/nacos/address/SimpleHttpTestUtils.java new file mode 100644 index 00000000000..d604c965901 --- /dev/null +++ b/address/src/test/java/com/alibaba/nacos/address/SimpleHttpTestUtils.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.address; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Map; + +/** + * @author pbting + * @date 2019-06-18 2:40 PM + */ +public class SimpleHttpTestUtils { + + private static final String REQUEST_METHOD_DELETE = "DELETE"; + private static final String REQUEST_METHOD_PUT = "PUT"; + private static final String REQUEST_METHOD_POST = "POST"; + private static final String REQUEST_METHOD_GET = "GET"; + + /** + * 连接超时 + */ + private static int CONNECT_TIME_OUT = 2000; + + /** + * 读取数据超时 + */ + private static int READ_TIME_OUT = 2000; + + /** + * 请求编码 + */ + public static String REQUEST_ENCODING = "UTF-8"; + + /** + * 接收编码 + */ + public static String RESPONSE_ENCODING = "UTF-8"; + + public static final short OK = 200; + + public static final short Bad_Request = 400; + + public static final short Internal_Server_Error = 500; + + public static final short PARAM_ERROR_NO_ANALYSESOR = 1000; + + /** + *

+     * 发送带参数的GET的HTTP请求
+     * 
+ * + * @param reqUrl HTTP请求URL + * @param paramMap 参数映射表 + * @return HTTP响应的字符串 + */ + public static String doGet(String reqUrl, Map paramMap, String recvEncoding) { + return doRequest(reqUrl, paramMap, REQUEST_METHOD_GET, recvEncoding); + } + + /** + *
+     * 发送带参数的POST的HTTP请求
+     * 
+ * + * @param reqUrl HTTP请求URL + * @param paramMap 参数映射表 + * @return HTTP响应的字符串 + */ + public static String doPost(String reqUrl, Map paramMap, String recvEncoding) { + return doRequest(reqUrl, paramMap, REQUEST_METHOD_POST, recvEncoding); + } + + /** + *
+     * 发送带参数的 PUT 的 HTTP 请求
+     * 
+ * + * @param reqUrl HTTP请求URL + * @param paramMap 参数映射表 + * @return HTTP响应的字符串 + */ + public static String doPut(String reqUrl, Map paramMap, String recvEncoding) { + return doRequest(reqUrl, paramMap, REQUEST_METHOD_PUT, recvEncoding); + } + + /** + *
+     * 发送带参数的 DELETE 的 HTTP 请求
+     * 
+ * + * @param reqUrl HTTP请求URL + * @param paramMap 参数映射表 + * @return HTTP响应的字符串 + */ + public static String doDelete(String reqUrl, Map paramMap, String recvEncoding) { + return doRequest(reqUrl, paramMap, REQUEST_METHOD_DELETE, recvEncoding); + } + + private static String doRequest(String reqUrl, Map paramMap, String reqMethod, String recvEncoding) { + + return doExecute(reqUrl, paramMap, reqMethod, recvEncoding); + } + + private static String doExecute(String reqUrl, Map paramMap, String reqMethod, String recvEncoding) { + HttpURLConnection urlCon = null; + String responseContent = null; + try { + StringBuilder params = new StringBuilder(); + if (paramMap != null) { + for (Map.Entry element : paramMap.entrySet()) { + params.append(element.getKey()); + params.append("="); + params.append(URLEncoder.encode(element.getValue(), REQUEST_ENCODING)); + params.append("&"); + } + + if (params.length() > 0) { + params = params.deleteCharAt(params.length() - 1); + } + + if (params.length() > 0 && + (REQUEST_METHOD_GET.equals(reqMethod) || REQUEST_METHOD_DELETE.equals(reqMethod))) { + reqUrl = reqUrl + "?" + params.toString(); + } + } + URL url = new URL(reqUrl); + urlCon = (HttpURLConnection) url.openConnection(); + urlCon.setRequestMethod(reqMethod); + urlCon.setConnectTimeout(CONNECT_TIME_OUT); + urlCon.setReadTimeout(READ_TIME_OUT); + urlCon.setDoOutput(true); + if (REQUEST_METHOD_POST.equals(reqMethod) || REQUEST_METHOD_PUT.equals(reqMethod)) { + byte[] b = params.toString().getBytes(); + urlCon.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + urlCon.setRequestProperty("Content-Length", String.valueOf(b.length)); + urlCon.getOutputStream().write(b, 0, b.length); + urlCon.getOutputStream().flush(); + urlCon.getOutputStream().close(); + } + InputStream in = urlCon.getInputStream(); + BufferedReader rd = new BufferedReader(new InputStreamReader(in, recvEncoding)); + String tempLine = rd.readLine(); + StringBuffer tempStr = new StringBuffer(); + while (tempLine != null) { + tempStr.append(tempLine); + tempLine = rd.readLine(); + } + responseContent = tempStr.toString(); + rd.close(); + in.close(); + + urlCon.getResponseMessage(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (urlCon != null) { + urlCon.disconnect(); + } + } + return responseContent; + } + +} diff --git a/api/pom.xml b/api/pom.xml index 40ec9da84ce..2fac328acf3 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -16,7 +16,7 @@ com.alibaba.nacos nacos-all - 1.0.2-SNAPSHOT + 1.1.0 4.0.0 diff --git a/api/src/main/java/com/alibaba/nacos/api/config/annotation/NacosConfigurationProperties.java b/api/src/main/java/com/alibaba/nacos/api/config/annotation/NacosConfigurationProperties.java index 2d2cf648066..98e94d01f3a 100644 --- a/api/src/main/java/com/alibaba/nacos/api/config/annotation/NacosConfigurationProperties.java +++ b/api/src/main/java/com/alibaba/nacos/api/config/annotation/NacosConfigurationProperties.java @@ -57,6 +57,15 @@ */ String dataId(); + /** + * set config type is yaml + * this method is deprecated, we support you use {@link #type()} to set config type + * + * @return default value false + */ + @Deprecated + boolean yaml() default false; + /** * config style * diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/AbstractHealthChecker.java b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/AbstractHealthChecker.java index f719c7d76d0..8f09604a505 100644 --- a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/AbstractHealthChecker.java +++ b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/AbstractHealthChecker.java @@ -52,7 +52,7 @@ public void setType(String type) { /** * used to JsonAdapter */ - public void jsonAdapterCallback(SerializeWriter writer){ + public void jsonAdapterCallback(SerializeWriter writer) { // do nothing } @@ -147,7 +147,7 @@ public boolean equals(Object obj) { return false; } - Http other = (Http)obj; + Http other = (Http) obj; if (!strEquals(type, other.getType())) { return false; @@ -259,7 +259,7 @@ public boolean equals(Object obj) { return false; } - Mysql other = (Mysql)obj; + Mysql other = (Mysql) obj; if (!strEquals(user, other.getUser())) { return false; diff --git a/client/pom.xml b/client/pom.xml index 0f6edbbfd86..30b7678cba1 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -16,7 +16,7 @@ com.alibaba.nacos nacos-all - 1.0.2-SNAPSHOT + 1.1.0 ../pom.xml diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java index 9461f950734..8f763746bc2 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java @@ -34,12 +34,10 @@ import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult; import com.alibaba.nacos.client.config.utils.IOUtils; -import com.alibaba.nacos.client.identify.Constants; import com.alibaba.nacos.client.utils.*; import org.slf4j.Logger; -import org.slf4j.Logger; /** * Serverlist Manager @@ -275,13 +273,23 @@ private void updateIfChanged(List newList) { LOGGER.warn("[update-serverlist] current serverlist from address server is empty!!!"); return; } + + List newServerAddrList = new ArrayList(); + for (String server : newList) { + if (server.startsWith(HTTP) || server.startsWith(HTTPS)) { + newServerAddrList.add(server); + } else { + newServerAddrList.add(HTTP + server); + } + } + /** * no change */ - if (newList.equals(serverUrls)) { + if (newServerAddrList.equals(serverUrls)) { return; } - serverUrls = new ArrayList(newList); + serverUrls = new ArrayList(newServerAddrList); iterator = iterator(); currentServerAddr = iterator.next(); diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java index a6f7fe65d6c..dc2c823bc72 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java @@ -238,7 +238,9 @@ public void deregisterInstance(String serviceName, Instance instance) throws Nac @Override public void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException { - beatReactor.removeBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), instance.getIp(), instance.getPort()); + if (instance.isEphemeral()) { + beatReactor.removeBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), instance.getIp(), instance.getPort()); + } serverProxy.deregisterService(NamingUtils.getGroupedName(serviceName, groupName), instance); } diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/beat/BeatReactor.java b/client/src/main/java/com/alibaba/nacos/client/naming/beat/BeatReactor.java index 31eb49d94f9..0998827e4f7 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/beat/BeatReactor.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/beat/BeatReactor.java @@ -64,6 +64,9 @@ public void addBeatInfo(String serviceName, BeatInfo beatInfo) { public void removeBeatInfo(String serviceName, String ip, int port) { NAMING_LOGGER.info("[BEAT] removing beat: {}:{}:{} from beat map.", serviceName, ip, port); BeatInfo beatInfo = dom2Beat.remove(buildKey(serviceName, ip, port)); + if (beatInfo == null) { + return; + } beatInfo.setStopped(true); MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size()); } @@ -83,10 +86,10 @@ public BeatTask(BeatInfo beatInfo) { @Override public void run() { - long result = serverProxy.sendBeat(beatInfo); if (beatInfo.isStopped()) { return; } + long result = serverProxy.sendBeat(beatInfo); long nextTime = result > 0 ? result : beatInfo.getPeriod(); executorService.schedule(new BeatTask(beatInfo), nextTime, TimeUnit.MILLISECONDS); } diff --git a/cmdb/pom.xml b/cmdb/pom.xml index 49485a428c6..b361d9bbed9 100644 --- a/cmdb/pom.xml +++ b/cmdb/pom.xml @@ -18,7 +18,7 @@ nacos-all com.alibaba.nacos - 1.0.2-SNAPSHOT + 1.1.0 ../pom.xml 4.0.0 diff --git a/common/pom.xml b/common/pom.xml index c6c16b157a7..d405c44f021 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -18,7 +18,7 @@ com.alibaba.nacos nacos-all - 1.0.2-SNAPSHOT + 1.1.0 ../pom.xml 4.0.0 diff --git a/config/pom.xml b/config/pom.xml index b2f9eb197e6..19806c0f404 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -17,7 +17,7 @@ com.alibaba.nacos nacos-all - 1.0.2-SNAPSHOT + 1.1.0 4.0.0 diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/DynamicDataSource.java b/config/src/main/java/com/alibaba/nacos/config/server/service/DynamicDataSource.java index 8a0bf69c582..ac8fe8bb488 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/DynamicDataSource.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/DynamicDataSource.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.config.server.service; import com.alibaba.nacos.config.server.utils.PropertyUtil; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @@ -30,6 +31,9 @@ @Component public class DynamicDataSource implements ApplicationContextAware { + @Autowired + private PropertyUtil propertyUtil; + private ApplicationContext applicationContext; @Override @@ -44,7 +48,7 @@ public ApplicationContext getApplicationContext() { public DataSourceService getDataSource() { DataSourceService dataSourceService = null; - if (STANDALONE_MODE && !PropertyUtil.isStandaloneUseMysql()) { + if (STANDALONE_MODE && !propertyUtil.isStandaloneUseMysql()) { dataSourceService = (DataSourceService)applicationContext.getBean("localDataSourceService"); } else { dataSourceService = (DataSourceService)applicationContext.getBean("basicDataSourceService"); diff --git a/console/pom.xml b/console/pom.xml index c8d5ab5a096..9f80b009daf 100644 --- a/console/pom.xml +++ b/console/pom.xml @@ -18,7 +18,7 @@ com.alibaba.nacos nacos-all - 1.0.2-SNAPSHOT + 1.1.0 nacos-console @@ -84,37 +84,8 @@ runtime + - nacos-server - - - maven-jar-plugin - - - - true - true - - - - - - org.springframework.boot - spring-boot-maven-plugin - 2.1.1.RELEASE - - com.alibaba.nacos.Nacos - ZIP - - - - - repackage - - - - - src/main/resources @@ -131,4 +102,52 @@ + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.4 + + + + + + + release-nacos + + nacos-server + + + maven-jar-plugin + + + + true + true + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.1.RELEASE + + com.alibaba.nacos.Nacos + ZIP + + + + + repackage + + + + + + + + diff --git a/console/src/main/resources/static/console-fe/src/index.js b/console/src/main/resources/static/console-fe/src/index.js index 1ce94559fbe..2bea03949e4 100644 --- a/console/src/main/resources/static/console-fe/src/index.js +++ b/console/src/main/resources/static/console-fe/src/index.js @@ -43,6 +43,7 @@ import ServiceList from './pages/ServiceManagement/ServiceList'; import ServiceDetail from './pages/ServiceManagement/ServiceDetail'; import SubscriberList from './pages/ServiceManagement/SubscriberList'; import ClusterNodeList from './pages/ClusterManagement/ClusterNodeList'; +import Welcome from './pages/Welcome/Welcome'; import reducers from './reducers'; import { changeLanguage } from './reducers/locale'; @@ -70,7 +71,8 @@ const store = createStore( ); const MENU = [ - { path: '/', exact: true, render: () => }, + { path: '/', exact: true, render: () => }, + { path: '/welcome', component: Welcome }, { path: '/namespace', component: Namespace }, { path: '/newconfig', component: Newconfig }, { path: '/configsync', component: Configsync }, diff --git a/console/src/main/resources/static/console-fe/src/locales/zh-CN.js b/console/src/main/resources/static/console-fe/src/locales/zh-CN.js index cdf3cd300b1..df9bf0e0997 100644 --- a/console/src/main/resources/static/console-fe/src/locales/zh-CN.js +++ b/console/src/main/resources/static/console-fe/src/locales/zh-CN.js @@ -257,7 +257,7 @@ const I18N_CONF = { importSucc: '导入成功', importAbort: '导入终止', importSuccBegin: '导入成功,导入了', - importSuccEnd: '项配制', + importSuccEnd: '项配置', importFail: '导入失败', importDataValidationError: '未读取到合法数据,请检查导入的数据文件。', metadataIllegal: '导入的元数据文件非法', @@ -266,24 +266,24 @@ const I18N_CONF = { skipImport: '跳过', overwriteImport: '覆盖', importRemind: '文件上传后将直接导入配置,请务必谨慎操作!', - samePreparation: '相同配制', + samePreparation: '相同配置', targetNamespace: '目标空间', conflictConfig: '检测到冲突的配置项', failureEntries: '失败的条目', unprocessedEntries: '未处理的条目', skippedEntries: '跳过的条目', - exportSelected: '导出选中的配制', + exportSelected: '导出选中的配置', clone: '克隆', - exportSelectedAlertTitle: '配制导出', - exportSelectedAlertContent: '请选择要导出的配制', + exportSelectedAlertTitle: '配置导出', + exportSelectedAlertContent: '请选择要导出的配置', cloneSucc: '克隆成功', cloneAbort: '克隆终止', cloneSuccBegin: '克隆成功,克隆了', - cloneSuccEnd: '项配制', + cloneSuccEnd: '项配置', cloneFail: '克隆失败', getNamespaceFailed: '获取命名空间失败', startCloning: '开始克隆', - cloningConfiguration: '克隆配制', + cloningConfiguration: '克隆配置', source: '源空间:', configurationNumber: '配置数量:', target: '目标空间:', diff --git a/console/src/main/resources/static/console-fe/src/pages/ConfigurationManagement/ConfigEditor/NewConfigEditor.js b/console/src/main/resources/static/console-fe/src/pages/ConfigurationManagement/ConfigEditor/NewConfigEditor.js index 80f92006dc1..c30050871eb 100644 --- a/console/src/main/resources/static/console-fe/src/pages/ConfigurationManagement/ConfigEditor/NewConfigEditor.js +++ b/console/src/main/resources/static/console-fe/src/pages/ConfigurationManagement/ConfigEditor/NewConfigEditor.js @@ -37,6 +37,7 @@ import { Grid, ConfigProvider, } from '@alifd/next'; +import { resolve } from 'url'; const { Row, Col } = Grid; @@ -95,7 +96,18 @@ class ConfigEditor extends React.Component { dataId: getParams('dataId').trim(), group, }, - () => this.getConfig() + () => + this.getConfig(true).then(res => { + if (!res) { + this.getConfig(); + return; + } + this.setState({ + isBeta: true, + tabActiveKey: 'beta', + betaPublishSuccess: true, + }); + }) ); } else { if (group) { @@ -154,14 +166,15 @@ class ConfigEditor extends React.Component { openDiff(cbName) { this.diffcb = cbName; let leftvalue = this.monacoEditor.getValue(); - let rightvalue = this.codeVal; + let rightvalue = this.codeVal || ''; leftvalue = leftvalue.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n'); rightvalue = rightvalue.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n'); this.diffEditorDialog.current.getInstance().openDialog(leftvalue, rightvalue); } clickTab(tabActiveKey) { - this.setState({ tabActiveKey }, () => this.getConfig(tabActiveKey === 'bata')); + console.log('tabActiveKey', tabActiveKey, tabActiveKey === 'beta'); + this.setState({ tabActiveKey }, () => this.getConfig(tabActiveKey === 'beta')); } getCodeVal() { @@ -191,11 +204,13 @@ class ConfigEditor extends React.Component { if (validateContent.validate({ content, type })) { return this._publishConfig(); } else { - Dialog.confirm({ - content: locale.codeValErrorPrompt, - onOk: () => this._publishConfig(), + return new Promise((resolve, reject) => { + Dialog.confirm({ + content: locale.codeValErrorPrompt, + onOk: () => resolve(this._publishConfig()), + onCancel: () => resolve(false), + }); }); - return false; } } @@ -226,7 +241,7 @@ class ConfigEditor extends React.Component { if (isNewConfig) { this.setState({ isNewConfig: false }); } - this.getConfig(); + this.getConfig(beta); } return res; }); @@ -235,13 +250,11 @@ class ConfigEditor extends React.Component { publishBeta() { return this._publishConfig(true).then(res => { if (res) { - this.setState( - { - betaPublishSuccess: true, - tabActiveKey: 'beta', - }, - () => this.getConfig(true) - ); + this.setState({ + betaPublishSuccess: true, + tabActiveKey: 'beta', + }); + return res; } }); } @@ -308,27 +321,31 @@ class ConfigEditor extends React.Component { ); } - getConfig(beta = false) { + getConfig(beta = false, decide = false) { const namespace = getParams('namespace'); const { dataId, group } = this.state.form; - return request - .get('v1/cs/configs', { - params: { - dataId, - group, - beta, - show: 'all', - namespaceId: namespace, - tenant: namespace, - }, - }) - .then(res => { - const { type, content, configTags } = res; - this.changeForm({ ...res, config_tags: configTags ? configTags.split(',') : [] }); - this.initMoacoEditor(type, content); - this.codeVal = content; - return res; - }); + const params = { + dataId, + group, + namespaceId: namespace, + tenant: namespace, + }; + if (beta) { + params.beta = true; + } + if (!beta) { + params.show = 'all'; + } + return request.get('v1/cs/configs', { params }).then(res => { + const form = beta ? res.data : res; + if (!form) return false; + const { type, content, configTags, betaIps } = form; + this.setState({ betaIps }); + this.changeForm({ ...form, config_tags: configTags ? configTags.split(',') : [] }); + this.initMoacoEditor(type, content); + this.codeVal = content; + return res; + }); } validation() { @@ -458,6 +475,7 @@ class ConfigEditor extends React.Component { this.setState({ betaIps })} /> )} @@ -465,9 +483,10 @@ class ConfigEditor extends React.Component { )} { - this.initMoacoEditor(type, ''); + this.initMoacoEditor(type, form.content); this.changeForm({ type }); }} > @@ -521,7 +540,7 @@ class ConfigEditor extends React.Component {