diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md
index da04fd312e7..73d1c482388 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.md
+++ b/.github/ISSUE_TEMPLATE/bug-report.md
@@ -21,7 +21,7 @@ A clear and concise description of what the bug is.
**Expected behavior**
A clear and concise description of what you expected to happen.
-**Acutally behavior**
+**Actually behavior**
A clear and concise description of what you actually to happen.
**How to Reproduce**
@@ -29,7 +29,7 @@ Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
-4. See error
+4. See errors
**Desktop (please complete the following information):**
- OS: [e.g. Centos]
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index fdc09b1c430..36e0e079d31 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,4 +34,8 @@ jobs:
- name: Build with Maven
run: mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
- name: Test With Maven
- run: mvn -Prelease-nacos clean test -DforkCount=0
+ run: mvn -Prelease-nacos clean test -DtrimStackTrace=false
+ - name: Codecov
+ uses: codecov/codecov-action@v3.1.0
+ with:
+ files: ./address/target/site/jacoco/jacoco.xml,./api/target/site/jacoco/jacoco.xml,./auth/target/site/jacoco/jacoco.xml,./client/target/site/jacoco/jacoco.xml,./common/target/site/jacoco/jacoco.xml,./consistency/target/site/jacoco/jacoco.xml,./console/target/site/jacoco/jacoco.xml,./core/target/site/jacoco/jacoco.xml,./naming/target/site/jacoco/jacoco.xml,./plugin-default-impl/target/site/jacoco/jacoco.xml,./plugin/auth/target/site/jacoco/jacoco.xml,./plugin/encryption/target/site/jacoco/jacoco.xml,./sys/target/site/jacoco/jacoco.xml
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index fc926b5db61..f345f29c586 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,42 +17,42 @@ Nacos welcome new participants of any role, including user, contributor, committ
![](http://acm-public.oss-cn-hangzhou.aliyuncs.com/contributor_definition.png)
-We encourage new comers actively join in Nacos projects and involving from user role to committer role, and even PMC role. In order to accomplish this, new comers needs to actively contribute in Nacos project. The following paragraph introduce how to contribute in Nacos way.
+We encourage newcomers actively joining in Nacos projects and involving from user roles to committer roles, and even PMC roles. In order to accomplish this, new comers needs to actively contribute in Nacos project. The following paragraph introduce how to contribute in Nacos way.
#### Open / pickup an issue for preparation
-If you find a typo in document, find a bug in code, or want new features, or want to give suggestions, you can [open an issue on GitHub](https://github.com/alibaba/Nacos/issues/new) to report it.
+If you find a typo in a document, find a bug in code or want new features, or want to give suggestions, you can [open an issue on GitHub](https://github.com/alibaba/Nacos/issues/new) to report it.
If you just want to contribute directly you can choose the issue below.
- [Contribution Welcome](https://github.com/alibaba/nacos/labels/contribution%20welcome): Heavily needed issue, but currently short of hand.
-- [good first issue](https://github.com/alibaba/nacos/labels/good%20first%20issue): Good for newcomers, new comer can pickup one for warm-up.
+- [good first issue](https://github.com/alibaba/nacos/labels/good%20first%20issue): Good for newcomers, newcomers can pick up one for warm-up.
We strongly value documentation and integration with other projects such as Spring Cloud, Kubernetes, Dubbo, etc. We are very glad to work on any issue for these aspects.
-Please note that any PR must be associated with a valid issue. Otherwise the PR will be rejected.
+Please note that any PR must be associated with a valid issue. Otherwise, the PR will be rejected.
-#### Begin your contribute
+#### Begin your contribution
Now if you want to contribute, please create a new pull request.
-We use the `develop` branch as the development branch, which indicates that this is a unstable branch.
+We use the `develop` branch as the development branch, which indicates that this is an unstable branch.
-Further more, our branching model complies to [https://nvie.com/posts/a-successful-git-branching-model/](https://nvie.com/posts/a-successful-git-branching-model/). We strongly suggest new comers walk through the above article before creating PR.
+Furthermore, our branching model complies with [https://nvie.com/posts/a-successful-git-branching-model/](https://nvie.com/posts/a-successful-git-branching-model/). We strongly suggest new comers walk through the above article before creating PR.
Now, if you are ready to create PR, here is the workflow for contributors:
1. Fork to your own
-2. Clone fork to local repository
+2. Clone fork to a local repository
3. Create a new branch and work on it
4. Keep your branch in sync
-5. Commit your changes (make sure your commit message concise)
+5. Commit your changes (make sure your commit message is concise)
6. Push your commits to your forked repository
@@ -73,7 +73,7 @@ When creating pull request:
6. After creating a PR, one or more reviewers will be assigned to the pull request.
-7. Before merging a PR, squash any fix review feedback, typo, merged, and rebased sorts of commits. The final commit message should be clear and concise.
+7. Before merging a PR, squash any fix review feedback, typo, merged and rebased sorts of commits. The final commit message should be clear and concise.
If your PR contains large changes, e.g. component refactor or new components, please write detailed documents about its design and usage.
@@ -86,7 +86,7 @@ Some principles:
- Readability - Important code should be well-documented. API should have Javadoc. Code style should be complied with the existing one.
-- Elegance: New functions, classes or components should be well designed.
+- Elegance: New functions, classes or components should be well-designed.
- Testability - 80% of the new code should be covered by unit test cases.
@@ -106,7 +106,7 @@ Generally speaking, contribute 8 non-trivial patches and get at least three diff
- ability to write good code (last but certainly not least)
-A current committer nominates you by slacking the team on the Nacos issue with label "nomination"
+A current committer nominates you by slacking the team on the Nacos issue with the label "nomination"
- your first and last name
@@ -114,10 +114,10 @@ A current committer nominates you by slacking the team on the Nacos issue with l
- an explanation of why you should be a committer,
-- Elaborate the top 3 PR and the associated issues the nominator has worked with you that can demonstrate your ability.
+- Elaborate on the top 3 PR and the associated issues the nominator has worked with you that can demonstrate your ability.
-Two other committer need to second your nomination. If no one objects in 5 working days (China), you're a committer. If anyone objects or wants more information, the committers discuss and usually come to a consensus (within the 5 working days). If issues cannot be resolved, there's a vote among current committers.
+Two other committers need to second your nomination. If no one objects in 5 working days (China), you're a committer. If anyone objects or wants more information, the committers discuss and usually come to a consensus (within the 5 working days). If issues cannot be resolved, there's a vote among current committers.
![](http://acm-public.oss-cn-hangzhou.aliyuncs.com/nomination_process.png)
diff --git a/REPORTING-BUGS.md b/REPORTING-BUGS.md
index e8e075430b7..4d600e6c7e8 100644
--- a/REPORTING-BUGS.md
+++ b/REPORTING-BUGS.md
@@ -1,14 +1,14 @@
-# How to Reporting bugs
+# How to report bugs
If any part of the Nacos project has bugs or documentation mistakes, please let us know by [opening an issue][Nacos-issue]. We treat bugs and mistakes very seriously and believe no issue is too small, anyOne is implement. Before creating a bug report, please check that an issue reporting the same problem does not already exist.
To make the bug report accurate and easy to understand, please try to create bug reports that are:
-- Specific. Include as much details as possible: which version, what environment, what configuration, etc. If the bug is related to running the Nacos server, please attach the Nacos log (the starting log with Nacos configuration is especially important).
+- Specific. Include as many details as possible: which version, what environment, what configuration, etc. If the bug is related to running the Nacos server, please attach the Nacos log (the starting log with Nacos configuration is especially important).
- Reproducible. Include the steps to reproduce the problem. We understand some issues might be hard to reproduce, please includes the steps that might lead to the problem. If possible, please attach the affected Nacos data dir and stack strace to the bug report.
-- Unique. Do not duplicate existing bug report.
+- Unique. Do not duplicate the existing bug report.
It may be worthwhile to read [Elika Etemad’s article on filing good bug reports][filing-good-bugs] before creating a bug report.
diff --git a/address/pom.xml b/address/pom.xml
index 004dca0a308..8b0185e5dd8 100644
--- a/address/pom.xml
+++ b/address/pom.xml
@@ -46,6 +46,11 @@
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
diff --git a/address/src/main/java/com/alibaba/nacos/address/config/AddressServerSecurityConfiguration.java b/address/src/main/java/com/alibaba/nacos/address/config/AddressServerSecurityConfiguration.java
new file mode 100644
index 00000000000..e6e09e9ee02
--- /dev/null
+++ b/address/src/main/java/com/alibaba/nacos/address/config/AddressServerSecurityConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1999-2022 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.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+/**
+ * nacos web security configuration.
+ * @author onewe
+ */
+@Configuration
+@Order(99)
+public class AddressServerSecurityConfiguration extends WebSecurityConfigurerAdapter {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.authorizeHttpRequests(requestMatcherRegistry -> requestMatcherRegistry.mvcMatchers("/nacos/v1/as/**").authenticated())
+ .csrf().disable().httpBasic();
+ }
+}
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
index fef68f10c56..6ec2425d43d 100644
--- a/address/src/main/java/com/alibaba/nacos/address/controller/AddressServerClusterController.java
+++ b/address/src/main/java/com/alibaba/nacos/address/controller/AddressServerClusterController.java
@@ -28,7 +28,6 @@
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.common.utils.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;
@@ -48,14 +47,19 @@
@RequestMapping({AddressServerConstants.ADDRESS_SERVER_REQUEST_URL + "/nodes"})
public class AddressServerClusterController {
- @Autowired
- private ServiceManager serviceManager;
+ private final ServiceManager serviceManager;
- @Autowired
- private AddressServerManager addressServerManager;
+ private final AddressServerManager addressServerManager;
+
+ private final AddressServerGeneratorManager addressServerGeneratorManager;
+
+ public AddressServerClusterController(ServiceManager serviceManager, AddressServerManager addressServerManager,
+ AddressServerGeneratorManager addressServerGeneratorManager) {
+ this.serviceManager = serviceManager;
+ this.addressServerManager = addressServerManager;
+ this.addressServerGeneratorManager = addressServerGeneratorManager;
+ }
- @Autowired
- private AddressServerGeneratorManager addressServerGeneratorManager;
/**
* Create new cluster.
@@ -146,7 +150,7 @@ public ResponseEntity deleteCluster(@RequestParam(required = false) Stri
List instanceList = addressServerGeneratorManager
.generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray);
serviceManager.removeInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, false,
- instanceList.toArray(new Instance[instanceList.size()]));
+ instanceList.toArray(new Instance[0]));
} else {
responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(checkResult);
}
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
index c310ecb9c9c..0fc03b0fd1a 100644
--- a/address/src/main/java/com/alibaba/nacos/address/controller/ServerListController.java
+++ b/address/src/main/java/com/alibaba/nacos/address/controller/ServerListController.java
@@ -21,7 +21,6 @@
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;
@@ -38,11 +37,15 @@
@RestController
public class ServerListController {
- @Autowired
- private ServiceManager serviceManager;
+ private final ServiceManager serviceManager;
- @Autowired
- private AddressServerGeneratorManager addressServerBuilderManager;
+ private final AddressServerGeneratorManager addressServerBuilderManager;
+
+ public ServerListController(ServiceManager serviceManager,
+ AddressServerGeneratorManager addressServerBuilderManager) {
+ this.serviceManager = serviceManager;
+ this.addressServerBuilderManager = addressServerBuilderManager;
+ }
/**
* Get cluster.
diff --git a/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java b/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java
index 03ae0c9a556..285b279ba7b 100644
--- a/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java
+++ b/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java
@@ -16,167 +16,233 @@
package com.alibaba.nacos.address;
+import com.alibaba.nacos.common.codec.Base64;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.util.LinkedMultiValueMap;
-import java.util.HashMap;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = {
+ "spring.security.user.password=123456", "spring.security.user.name=user"})
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";
+ private static final String HTTP_BASIC_INFO = getHttpBasicInfo();
- //-----------------product=nacos,cluster=DEFAULT -------------------//
+ @Autowired
+ private TestRestTemplate restTemplate;
- @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);
+ @BeforeClass
+ public static void before() {
+ System.setProperty("nacos.standalone", "true");
+ System.setProperty("embeddedStorage", "true");
}
- @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);
+ @AfterClass
+ public static void teardown() {
+ System.clearProperty("nacos.standalone");
+ System.clearProperty("embeddedStorage");
}
- @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);
+ private static String getHttpBasicInfo() {
+ String userName = "user";
+ String password = "123456";
+
+ String info = userName + ":" + password;
+
+ final byte[] bytes = Base64.encodeBase64(info.getBytes(StandardCharsets.UTF_8));
+
+ return "Basic " + new String(bytes, StandardCharsets.UTF_8);
}
@Test
- public void putCluster() {
+ public void postClusterWithoutLogin() {
+
+ String ips = "127.0.0.100,127.0.0.102,127.0.0.104";
+ LinkedMultiValueMap params = new LinkedMultiValueMap<>(1);
+ params.add("ips", ips);
+
+ final ResponseEntity postClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.post("/nacos/v1/as/nodes").body(params), String.class);
- 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);
+ Assert.assertEquals(postClusterResponseEntity.getStatusCode(), HttpStatus.UNAUTHORIZED);
}
- //-----------------product=config,cluster=cluster01 -------------------//
-
@Test
- public void postClusterWithProduct() {
+ public void postCluster() throws InterruptedException {
+
+ String ips = "127.0.0.100,127.0.0.102,127.0.0.104";
+ LinkedMultiValueMap params = new LinkedMultiValueMap<>(1);
+ params.add("ips", ips);
+
+ final ResponseEntity postClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO)
+ .body(params), String.class);
+
+ Assert.assertNotNull(postClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue());
+
+ TimeUnit.MILLISECONDS.sleep(500L);
+
+ final ResponseEntity getClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.get("/nacos/serverlist").build(), String.class);
+
+ Assert.assertNotNull(getClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), getClusterResponseEntity.getStatusCodeValue());
- 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);
+ public void deleteClusterWithoutLogin() {
+ LinkedMultiValueMap params = new LinkedMultiValueMap<>(1);
+ params.add("ips", "127.0.0.104");
+
+ final ResponseEntity postClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.post("/nacos/v1/as/nodes").body(params), String.class);
+ Assert.assertEquals(postClusterResponseEntity.getStatusCode(), HttpStatus.UNAUTHORIZED);
}
@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);
+ public void deleteCluster() throws InterruptedException {
+
+ LinkedMultiValueMap params = new LinkedMultiValueMap<>(1);
+ params.add("ips", "127.0.0.104");
+
+ final ResponseEntity postClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO)
+ .body(params), String.class);
+
+ Assert.assertNotNull(postClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue());
+
+ TimeUnit.MILLISECONDS.sleep(500L);
+
+ final ResponseEntity deleteClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.delete("/nacos/v1/as/nodes?ips={ips}", "127.0.0.104")
+ .header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO).build(), String.class);
+
+ Assert.assertNotNull(deleteClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), deleteClusterResponseEntity.getStatusCodeValue());
}
@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);
+ public void postClusterWithProduct() throws InterruptedException {
+
+ LinkedMultiValueMap params = new LinkedMultiValueMap<>(2);
+
+ String ips = "127.0.0.101,127.0.0.102,127.0.0.103";
+ params.add("ips", ips);
+ params.add("product", PRODUCT_CONFIG);
+
+ final ResponseEntity postClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO)
+ .body(params), String.class);
+ Assert.assertNotNull(postClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue());
+
+ TimeUnit.MILLISECONDS.sleep(500L);
+
+ final ResponseEntity getClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.get("/{product}/serverlist", PRODUCT_CONFIG).build(), String.class);
+
+ Assert.assertNotNull(getClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), getClusterResponseEntity.getStatusCodeValue());
+
+ final String body = getClusterResponseEntity.getBody();
+ Assert.assertNotNull(body);
}
@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);
+ public void deleteClusterWithProduct() throws InterruptedException {
+
+ LinkedMultiValueMap params = new LinkedMultiValueMap<>(1);
+ params.add("ips", "127.0.0.104");
+ params.add("product", PRODUCT_CONFIG);
+
+ final ResponseEntity postClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO)
+ .body(params), String.class);
+ Assert.assertNotNull(postClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue());
+
+ TimeUnit.MILLISECONDS.sleep(500L);
+
+ final ResponseEntity deleteClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.delete("/nacos/v1/as/nodes?product={product}&ips={ips}", PRODUCT_CONFIG, "127.0.0.104")
+ .header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO).build(), String.class);
+
+ Assert.assertNotNull(deleteClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), deleteClusterResponseEntity.getStatusCodeValue());
}
- //-----------------product=naming,cluster=cluster01 -------------------//
-
@Test
- public void postClusterWithProductAndCluster() {
+ public void postClusterWithProductAndCluster() throws InterruptedException {
+ LinkedMultiValueMap params = new LinkedMultiValueMap<>(1);
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);
+
+ params.add("ips", ips);
+ params.add("product", PRODUCT_NAMING);
+ params.add("cluster", "cluster01");
+
+ final ResponseEntity postClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO)
+ .body(params), String.class);
+ Assert.assertNotNull(postClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue());
+
+ TimeUnit.MILLISECONDS.sleep(500L);
+
+ final ResponseEntity getClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.get("/{product}/{cluster}", PRODUCT_NAMING, "cluster01").build(), String.class);
+
+ Assert.assertNotNull(getClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), getClusterResponseEntity.getStatusCodeValue());
+
+ final String body = getClusterResponseEntity.getBody();
+ Assert.assertNotNull(body);
}
@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);
+ public void deleteClusterWithProductAndCluster() throws InterruptedException {
+
+ LinkedMultiValueMap params = new LinkedMultiValueMap<>(1);
+ params.add("ips", "127.0.0.104");
+ params.add("product", PRODUCT_NAMING);
+ params.add("cluster", "cluster01");
+
+ final ResponseEntity postClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO)
+ .body(params), String.class);
+ Assert.assertNotNull(postClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue());
+
+ TimeUnit.MILLISECONDS.sleep(500L);
+
+ final ResponseEntity deleteClusterResponseEntity = restTemplate.exchange(
+ RequestEntity.delete("/nacos/v1/as/nodes?product={product}&cluster={cluster}&ips={ips}", PRODUCT_NAMING,
+ "cluster01", "127.0.0.104").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO).build(),
+ String.class);
+
+ Assert.assertNotNull(deleteClusterResponseEntity);
+ Assert.assertEquals(HttpStatus.OK.value(), deleteClusterResponseEntity.getStatusCodeValue());
}
- @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/SimpleHttpTestUtils.java b/address/src/test/java/com/alibaba/nacos/address/SimpleHttpTestUtils.java
deleted file mode 100644
index 2a00c59c415..00000000000
--- a/address/src/test/java/com/alibaba/nacos/address/SimpleHttpTestUtils.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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 com.alibaba.nacos.common.utils.IoUtils;
-
-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;
-
-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 final int CONNECT_TIME_OUT = 2000;
-
- /**
- * 读取数据超时.
- */
- private static final int READ_TIME_OUT = 2000;
-
- /**
- * 请求编码.
- */
- public static final String REQUEST_ENCODING = "UTF-8";
-
- /**
- * 接收编码.
- */
- public static final 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 {
- IoUtils.closeQuietly(urlCon);
- }
- return responseContent;
- }
-
-}
diff --git a/address/src/test/java/com/alibaba/nacos/address/component/AddressServerGeneratorManagerTest.java b/address/src/test/java/com/alibaba/nacos/address/component/AddressServerGeneratorManagerTest.java
new file mode 100644
index 00000000000..0f42249bf54
--- /dev/null
+++ b/address/src/test/java/com/alibaba/nacos/address/component/AddressServerGeneratorManagerTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.component;
+
+import com.alibaba.nacos.address.constant.AddressServerConstants;
+import com.alibaba.nacos.naming.core.Instance;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AddressServerGeneratorManagerTest {
+
+ @Test
+ public void testGenerateProductName() {
+ AddressServerGeneratorManager manager = new AddressServerGeneratorManager();
+ final String blankName = manager.generateProductName("");
+ Assert.assertEquals(AddressServerConstants.ALIWARE_NACOS_DEFAULT_PRODUCT_NAME, blankName);
+
+ final String defaultName = manager.generateProductName(AddressServerConstants.DEFAULT_PRODUCT);
+ Assert.assertEquals(AddressServerConstants.ALIWARE_NACOS_DEFAULT_PRODUCT_NAME, defaultName);
+
+ final String testName = manager.generateProductName("test");
+ Assert.assertEquals("nacos.as.test", testName);
+
+ }
+
+ @Test
+ public void testGenerateInstancesByIps() {
+ AddressServerGeneratorManager manager = new AddressServerGeneratorManager();
+ final List empty = manager.generateInstancesByIps(null, null, null, null);
+ Assert.assertNotNull(empty);
+ Assert.assertTrue(empty.isEmpty());
+
+ String[] ipArray = new String[]{"192.168.3.1:8848", "192.168.3.2:8848", "192.168.3.3:8848"};
+ final List instanceList = manager.generateInstancesByIps("DEFAULT_GROUP@@nacos.as.test", "test", "test",
+ ipArray);
+ Assert.assertNotNull(instanceList);
+ Assert.assertFalse(instanceList.isEmpty());
+ Assert.assertEquals(3, instanceList.size());
+
+ final Instance instance1 = instanceList.get(0);
+ Assert.assertEquals("192.168.3.1", instance1.getIp());
+
+ final Instance instance2 = instanceList.get(1);
+ Assert.assertEquals("192.168.3.2", instance2.getIp());
+
+ final Instance instance3 = instanceList.get(2);
+ Assert.assertEquals("192.168.3.3", instance3.getIp());
+
+ }
+
+ @Test
+ public void testGenerateResponseIps() {
+ final List instanceList = new ArrayList<>();
+ Instance instance1 = new Instance();
+ instance1.setIp("192.168.3.1");
+ instance1.setPort(8848);
+
+ Instance instance2 = new Instance();
+ instance2.setIp("192.168.3.2");
+ instance2.setPort(8848);
+
+ Instance instance3 = new Instance();
+ instance3.setIp("192.168.3.3");
+ instance3.setPort(8848);
+
+ instanceList.add(instance1);
+ instanceList.add(instance2);
+ instanceList.add(instance3);
+
+ AddressServerGeneratorManager manager = new AddressServerGeneratorManager();
+ final String ipListStr = manager.generateResponseIps(instanceList);
+
+ StringBuilder expectStr = new StringBuilder();
+ final StringBuilder ret = expectStr
+ .append("192.168.3.1:8848").append('\n')
+ .append("192.168.3.2:8848").append('\n')
+ .append("192.168.3.3:8848").append('\n');
+ Assert.assertEquals(ret.toString(), ipListStr);
+
+ }
+
+ @Test
+ public void testGenerateNacosServiceName() {
+ AddressServerGeneratorManager manager = new AddressServerGeneratorManager();
+
+ final String containDefault = manager.generateNacosServiceName("DEFAULT_GROUP@@test");
+ Assert.assertEquals("DEFAULT_GROUP@@test", containDefault);
+
+ final String product = manager.generateNacosServiceName("product");
+ Assert.assertEquals("DEFAULT_GROUP@@product", product);
+ }
+
+}
diff --git a/address/src/test/java/com/alibaba/nacos/address/component/AddressServerManagerTests.java b/address/src/test/java/com/alibaba/nacos/address/component/AddressServerManagerTests.java
index 4141af90f78..25c6441dbb2 100644
--- a/address/src/test/java/com/alibaba/nacos/address/component/AddressServerManagerTests.java
+++ b/address/src/test/java/com/alibaba/nacos/address/component/AddressServerManagerTests.java
@@ -41,4 +41,23 @@ public void getDefaultClusterNameIfEmpty() {
assertEquals("otherServerList", ADDRESS_SERVER_MANAGER.getDefaultClusterNameIfEmpty("otherServerList"));
}
+ @Test
+ public void testGetRawClusterName() {
+ assertEquals("serverList", ADDRESS_SERVER_MANAGER.getRawClusterName("serverList"));
+ assertEquals(AddressServerConstants.DEFAULT_GET_CLUSTER, ADDRESS_SERVER_MANAGER.getRawClusterName(""));
+ }
+
+ @Test
+ public void testSplitIps() {
+ final String[] emptyArr = ADDRESS_SERVER_MANAGER.splitIps("");
+ assertEquals(0, emptyArr.length);
+ final String[] one = ADDRESS_SERVER_MANAGER.splitIps("192.168.1.12:8848");
+ assertEquals(1, one.length);
+ assertEquals("192.168.1.12:8848", one[0]);
+ final String[] two = ADDRESS_SERVER_MANAGER.splitIps("192.168.1.12:8848,192.268.3.33:8848");
+ assertEquals(2, two.length);
+ assertEquals("192.168.1.12:8848", two[0]);
+ assertEquals("192.268.3.33:8848", two[1]);
+ }
+
}
diff --git a/address/src/test/java/com/alibaba/nacos/address/controller/AddressServerClusterControllerTest.java b/address/src/test/java/com/alibaba/nacos/address/controller/AddressServerClusterControllerTest.java
new file mode 100644
index 00000000000..366ef5008eb
--- /dev/null
+++ b/address/src/test/java/com/alibaba/nacos/address/controller/AddressServerClusterControllerTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.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.api.common.Constants;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.naming.core.Service;
+import com.alibaba.nacos.naming.core.ServiceManager;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AddressServerClusterControllerTest {
+
+ @Mock
+ private ServiceManager serviceManager;
+
+ private MockMvc mockMvc;
+
+ @Before
+ public void before() {
+ mockMvc = MockMvcBuilders.standaloneSetup(new AddressServerClusterController(serviceManager, new AddressServerManager(),
+ new AddressServerGeneratorManager())).build();
+ }
+
+ @Test
+ public void testPostCluster() throws Exception {
+
+ mockMvc.perform(post("/nacos/v1/as/nodes")
+ .param("product", "default")
+ .param("cluster", "serverList")
+ .param("ips", "192.168.3.1,192.168.3.2"))
+ .andExpect(status().isOk());
+
+ }
+
+ @Test
+ public void testPostClusterWithErrorIps() throws Exception {
+ mockMvc.perform(post("/nacos/v1/as/nodes")
+ .param("product", "default")
+ .param("cluster", "serverList")
+ .param("ips", "192.168.1"))
+ .andExpect(status().isBadRequest());
+ }
+
+ @Test
+ public void testPostClusterThrowException() throws Exception {
+
+ Mockito.doThrow(new NacosException(500, "create service error")).when(serviceManager)
+ .createServiceIfAbsent(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID), Mockito.eq(
+ Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"),
+ Mockito.eq(false), Mockito.any());
+
+ mockMvc.perform(post("/nacos/v1/as/nodes")
+ .param("product", "default")
+ .param("cluster", "serverList")
+ .param("ips", "192.168.1"))
+ .andExpect(status().isInternalServerError());
+
+ }
+
+ @Test
+ public void testDeleteCluster() throws Exception {
+
+ Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
+ Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
+ .thenReturn(new Service(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"));
+
+ mockMvc.perform(delete("/nacos/v1/as/nodes")
+ .param("product", "default")
+ .param("cluster", "serverList")
+ .param("ips", "192.168.3.1,192.168.3.2")
+ ).andExpect(status().isOk());
+
+ }
+
+ @Test
+ public void testDeleteClusterCannotFindService() throws Exception {
+
+ mockMvc.perform(delete("/nacos/v1/as/nodes")
+ .param("product", "default")
+ .param("cluster", "serverList")
+ .param("ips", "192.168.3.1,192.168.3.2")
+ ).andExpect(status().isNotFound());
+ }
+
+ @Test
+ public void testDeleteClusterEmptyIps() throws Exception {
+
+ Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
+ Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
+ .thenReturn(new Service(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"));
+
+ mockMvc.perform(delete("/nacos/v1/as/nodes")
+ .param("product", "default")
+ .param("cluster", "serverList")
+ .param("ips", "")
+ ).andExpect(status().isBadRequest());
+ }
+
+ @Test
+ public void testDeleteClusterErrorIps() throws Exception {
+
+ Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
+ Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
+ .thenReturn(new Service(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"));
+
+ mockMvc.perform(delete("/nacos/v1/as/nodes")
+ .param("product", "default")
+ .param("cluster", "serverList")
+ .param("ips", "192.168.1")
+ ).andExpect(status().isBadRequest());
+ }
+
+ @Test
+ public void testDeleteClusterThrowException() throws Exception {
+
+ Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
+ Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
+ .thenReturn(new Service(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"));
+
+ Mockito.doThrow(new NacosException(500, "remove service error"))
+ .when(serviceManager)
+ .removeInstance(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
+ Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"),
+ Mockito.eq(false),
+ Mockito.any());
+
+ mockMvc.perform(delete("/nacos/v1/as/nodes")
+ .param("product", "default")
+ .param("cluster", "serverList")
+ .param("ips", "192.168.3.1,192.168.3.2")
+ ).andExpect(status().isInternalServerError());
+ }
+
+}
diff --git a/address/src/test/java/com/alibaba/nacos/address/controller/ServerListControllerTest.java b/address/src/test/java/com/alibaba/nacos/address/controller/ServerListControllerTest.java
new file mode 100644
index 00000000000..43fbaa9fddf
--- /dev/null
+++ b/address/src/test/java/com/alibaba/nacos/address/controller/ServerListControllerTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.controller;
+
+import com.alibaba.nacos.address.component.AddressServerGeneratorManager;
+import com.alibaba.nacos.address.constant.AddressServerConstants;
+import com.alibaba.nacos.api.common.Constants;
+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.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ServerListControllerTest {
+
+ @Mock
+ private ServiceManager serviceManager;
+
+ private MockMvc mockMvc;
+
+ @Before
+ public void before() {
+ this.mockMvc = MockMvcBuilders
+ .standaloneSetup(new ServerListController(serviceManager, new AddressServerGeneratorManager()))
+ .build();
+ }
+
+ @Test
+ public void testGetCluster() throws Exception {
+
+ final Service service = new Service(
+ Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default");
+
+ Cluster cluster = new Cluster();
+ cluster.setName("serverList");
+ cluster.setService(service);
+
+ final HashMap clusterMap = new HashMap<>(1);
+ clusterMap.put("serverList", cluster);
+ service.setClusterMap(clusterMap);
+
+ List list = new ArrayList<>(2);
+ list.add(new Instance("192.168.3.1", 8848));
+ list.add(new Instance("192.168.3.2", 8848));
+ cluster.updateIps(list, false);
+
+ Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
+ Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
+ .thenReturn(service);
+
+ mockMvc.perform(get("/nacos/serverList"))
+ .andExpect(status().isOk());
+
+ }
+
+ @Test
+ public void testGetClusterCannotFindService() throws Exception {
+
+ mockMvc.perform(get("/default/serverList"))
+ .andExpect(status().isNotFound());
+
+ }
+
+ @Test
+ public void testGetClusterCannotFindCluster() throws Exception {
+
+ final Service service = new Service(
+ Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default");
+
+ final HashMap clusterMap = new HashMap<>(1);
+ service.setClusterMap(clusterMap);
+
+ Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
+ Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
+ .thenReturn(service);
+
+ mockMvc.perform(get("/nacos/serverList"))
+ .andExpect(status().isNotFound());
+
+ }
+}
diff --git a/api/pom.xml b/api/pom.xml
index 34e8d182ab3..5c9a9658a35 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -97,10 +97,6 @@
io.grpc
grpc-stub
-
- io.netty
- netty-all
-
com.google.api.grpc
proto-google-common-protos
diff --git a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java
index 2d35be79a98..226a2e3a7ee 100644
--- a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java
+++ b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java
@@ -86,6 +86,10 @@ public class Constants {
public static final String USERNAME = "username";
public static final String TOKEN_REFRESH_WINDOW = "tokenRefreshWindow";
+
+ public static final Integer SDK_GRPC_PORT_DEFAULT_OFFSET = 1000;
+
+ public static final Integer CLUSTER_GRPC_PORT_DEFAULT_OFFSET = 1001;
/**
* second.
@@ -184,7 +188,7 @@ public class Constants {
public static final String NULL_STRING = "null";
- public static final String NUMBER_PATTERN = "^\\d+$";
+ public static final String NUMBER_PATTERN_STRING = "^\\d+$";
public static final String ANY_PATTERN = ".*";
@@ -210,6 +214,8 @@ public class Constants {
public static final String CHARSET_KEY = "charset";
+ public static final String CLUSTER_NAME_PATTERN_STRING = "^[0-9a-zA-Z-]+$";
+
/**
* The constants in config directory.
*/
diff --git a/api/src/main/java/com/alibaba/nacos/api/config/ConfigType.java b/api/src/main/java/com/alibaba/nacos/api/config/ConfigType.java
index ce5d8d0f0ae..2073183c331 100644
--- a/api/src/main/java/com/alibaba/nacos/api/config/ConfigType.java
+++ b/api/src/main/java/com/alibaba/nacos/api/config/ConfigType.java
@@ -65,7 +65,7 @@ public enum ConfigType {
private final String type;
- private static final Map LOCAL_MAP = new HashMap();
+ private static final Map LOCAL_MAP = new HashMap<>();
static {
for (ConfigType configType : values()) {
diff --git a/api/src/main/java/com/alibaba/nacos/api/config/convert/NacosConfigConverter.java b/api/src/main/java/com/alibaba/nacos/api/config/convert/NacosConfigConverter.java
index f6527fc9c10..b66bff0e0bf 100644
--- a/api/src/main/java/com/alibaba/nacos/api/config/convert/NacosConfigConverter.java
+++ b/api/src/main/java/com/alibaba/nacos/api/config/convert/NacosConfigConverter.java
@@ -36,7 +36,7 @@ public interface NacosConfigConverter {
/**
* Convert the Nacos' config of type S to target type T.
*
- * @param config the Naocs's config to convert, which must be an instance of S (never {@code null})
+ * @param config the Nacos's config to convert, which must be an instance of S (never {@code null})
* @return the converted object, which must be an instance of T (potentially {@code null})
*/
T convert(String config);
diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigBatchListenRequest.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigBatchListenRequest.java
index 5e4cc9bcb17..f01e3b32056 100644
--- a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigBatchListenRequest.java
+++ b/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigBatchListenRequest.java
@@ -32,7 +32,7 @@ public class ConfigBatchListenRequest extends AbstractConfigRequest {
*/
private boolean listen = true;
- private List configListenContexts = new ArrayList();
+ private List configListenContexts = new ArrayList<>();
/**
* add listen config.
diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigChangeBatchListenResponse.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigChangeBatchListenResponse.java
index 72fc7ba5c35..6b3cc813258 100644
--- a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigChangeBatchListenResponse.java
+++ b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigChangeBatchListenResponse.java
@@ -30,7 +30,7 @@
*/
public class ConfigChangeBatchListenResponse extends Response {
- List changedConfigs = new ArrayList();
+ List changedConfigs = new ArrayList<>();
public ConfigChangeBatchListenResponse() {
}
diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigPublishResponse.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigPublishResponse.java
index ce9f8012d2f..19b70f2fd6e 100644
--- a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigPublishResponse.java
+++ b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigPublishResponse.java
@@ -23,7 +23,7 @@
* ConfigPublishResponse.
*
* @author liuzunfei
- * @version $Id: ConfigPubishResponse.java, v 0.1 2020年07月16日 4:59 PM liuzunfei Exp $
+ * @version $Id: ConfigPublishResponse.java, v 0.1 2020年07月16日 4:59 PM liuzunfei Exp $
*/
public class ConfigPublishResponse extends Response {
diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigRemoveResponse.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigRemoveResponse.java
index 7edf4108d9f..f32c9f4338f 100644
--- a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigRemoveResponse.java
+++ b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigRemoveResponse.java
@@ -20,10 +20,10 @@
import com.alibaba.nacos.api.remote.response.ResponseCode;
/**
- * ConfigPubishResponse.
+ * ConfigRemoveResponse.
*
* @author liuzunfei
- * @version $Id: ConfigPubishResponse.java, v 0.1 2020年07月16日 4:59 PM liuzunfei Exp $
+ * @version $Id: ConfigRemoveResponse.java, v 0.1 2020年07月16日 4:59 PM liuzunfei Exp $
*/
public class ConfigRemoveResponse extends Response {
diff --git a/api/src/main/java/com/alibaba/nacos/api/exception/runtime/NacosDeserializationException.java b/api/src/main/java/com/alibaba/nacos/api/exception/runtime/NacosDeserializationException.java
index 73c01eda832..e5c52a9bb92 100644
--- a/api/src/main/java/com/alibaba/nacos/api/exception/runtime/NacosDeserializationException.java
+++ b/api/src/main/java/com/alibaba/nacos/api/exception/runtime/NacosDeserializationException.java
@@ -33,6 +33,8 @@ public class NacosDeserializationException extends NacosRuntimeException {
private static final String MSG_FOR_SPECIFIED_CLASS = "Nacos deserialize for class [%s] failed. ";
+ private static final String ERROR_MSG_FOR_SPECIFIED_CLASS = "Nacos deserialize for class [%s] failed, cause error[%s]. ";
+
private Class> targetClass;
public NacosDeserializationException() {
@@ -53,12 +55,12 @@ public NacosDeserializationException(Throwable throwable) {
}
public NacosDeserializationException(Class> targetClass, Throwable throwable) {
- super(DESERIALIZE_ERROR_CODE, String.format(MSG_FOR_SPECIFIED_CLASS, targetClass.getName()), throwable);
+ super(DESERIALIZE_ERROR_CODE, String.format(ERROR_MSG_FOR_SPECIFIED_CLASS, targetClass.getName(), throwable.getMessage()), throwable);
this.targetClass = targetClass;
}
public NacosDeserializationException(Type targetType, Throwable throwable) {
- super(DESERIALIZE_ERROR_CODE, String.format(MSG_FOR_SPECIFIED_CLASS, targetType.toString()), throwable);
+ super(DESERIALIZE_ERROR_CODE, String.format(ERROR_MSG_FOR_SPECIFIED_CLASS, targetType.toString(), throwable.getMessage()), throwable);
}
public Class> getTargetClass() {
diff --git a/api/src/main/java/com/alibaba/nacos/api/grpc/auto/Payload.java b/api/src/main/java/com/alibaba/nacos/api/grpc/auto/Payload.java
index 0b4ffa223ca..c39ba61f54b 100644
--- a/api/src/main/java/com/alibaba/nacos/api/grpc/auto/Payload.java
+++ b/api/src/main/java/com/alibaba/nacos/api/grpc/auto/Payload.java
@@ -613,8 +613,7 @@ public MetadataOrBuilder getMetadataOrBuilder() {
Metadata, Metadata.Builder, MetadataOrBuilder>
getMetadataFieldBuilder() {
if (metadataBuilder_ == null) {
- metadataBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
- Metadata, Metadata.Builder, MetadataOrBuilder>(
+ metadataBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<>(
getMetadata(),
getParentForChildren(),
isClean());
@@ -730,8 +729,7 @@ public com.google.protobuf.AnyOrBuilder getBodyOrBuilder() {
com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder>
getBodyFieldBuilder() {
if (bodyBuilder_ == null) {
- bodyBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
- com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder>(
+ bodyBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<>(
getBody(),
getParentForChildren(),
isClean());
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/NamingService.java b/api/src/main/java/com/alibaba/nacos/api/naming/NamingService.java
index 753629acfd8..be6170cd542 100644
--- a/api/src/main/java/com/alibaba/nacos/api/naming/NamingService.java
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/NamingService.java
@@ -96,6 +96,17 @@ void registerInstance(String serviceName, String groupName, String ip, int port,
*/
void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException;
+ /**
+ * batch register instance to service with specified instance properties.
+ *
+ * @param serviceName name of service
+ * @param groupName group of service
+ * @param instances instances to register
+ * @throws NacosException nacos exception
+ * @since 2.1.1
+ */
+ void batchRegisterInstance(String serviceName, String groupName, List instances) throws NacosException;
+
/**
* deregister instance from a service.
*
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Cluster.java b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Cluster.java
index 547ad6481dc..7ec16abd7ad 100644
--- a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Cluster.java
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Cluster.java
@@ -66,7 +66,7 @@ public class Cluster implements Serializable {
*/
private boolean useIPPort4Check = true;
- private Map metadata = new HashMap();
+ private Map metadata = new HashMap<>();
public Cluster() {
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Instance.java b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Instance.java
index 15a5d0d0ece..58acefe9139 100644
--- a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Instance.java
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Instance.java
@@ -18,7 +18,7 @@
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.PreservedMetadataKeys;
-import com.alibaba.nacos.api.utils.StringUtils;
+import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@@ -26,8 +26,6 @@
import java.util.HashMap;
import java.util.Map;
-import static com.alibaba.nacos.api.common.Constants.NUMBER_PATTERN;
-
/**
* Instance.
*
@@ -88,7 +86,7 @@ public class Instance implements Serializable {
/**
* user extended attributes.
*/
- private Map metadata = new HashMap();
+ private Map metadata = new HashMap<>();
public String getInstanceId() {
return this.instanceId;
@@ -162,7 +160,7 @@ public void setMetadata(final Map metadata) {
*/
public void addMetadata(final String key, final String value) {
if (metadata == null) {
- metadata = new HashMap(4);
+ metadata = new HashMap<>(4);
}
metadata.put(key, value);
}
@@ -252,7 +250,7 @@ private long getMetaDataByKeyWithDefault(final String key, final long defaultVal
return defaultValue;
}
final String value = getMetadata().get(key);
- if (!StringUtils.isEmpty(value) && value.matches(NUMBER_PATTERN)) {
+ if (NamingUtils.isNumber(value)) {
return Long.parseLong(value);
}
return defaultValue;
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Service.java b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Service.java
index 82b4580f3c9..08fa6d269ca 100644
--- a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Service.java
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/Service.java
@@ -54,7 +54,7 @@ public class Service implements Serializable {
*/
private String groupName;
- private Map metadata = new HashMap();
+ private Map metadata = new HashMap<>();
public Service() {
}
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/ServiceInfo.java b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/ServiceInfo.java
index bf6fcee3421..811177a5414 100644
--- a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/ServiceInfo.java
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/ServiceInfo.java
@@ -55,7 +55,7 @@ public class ServiceInfo {
private long cacheMillis = 1000L;
- private List hosts = new ArrayList();
+ private List hosts = new ArrayList<>();
private long lastRefTime = 0L;
@@ -77,7 +77,7 @@ public void setAllIPs(boolean allIPs) {
}
/**
- * There is only one form of the key:groupName@@name@clusters. This constuctor used by DiskCache.read(String) and
+ * There is only one form of the key:groupName@@name@clusters. This constructor used by DiskCache.read(String) and
* FailoverReactor.FailoverFileReader,you should know that 'groupName' must not be null,and 'clusters' can be null.
*/
public ServiceInfo(String key) {
@@ -96,7 +96,7 @@ public ServiceInfo(String key) {
this.name = keys[serviceNameIndex];
} else {
//defensive programming
- throw new IllegalArgumentException("Cann't parse out 'groupName',but it must not be null!");
+ throw new IllegalArgumentException("Can't parse out 'groupName',but it must not be null!");
}
}
@@ -126,7 +126,7 @@ public void addAllHosts(List extends Instance> hosts) {
}
public List getHosts() {
- return new ArrayList(hosts);
+ return new ArrayList<>(hosts);
}
public boolean isValid() {
@@ -187,7 +187,7 @@ public boolean validate() {
return false;
}
- List validHosts = new ArrayList();
+ List validHosts = new ArrayList<>();
for (Instance host : hosts) {
if (!host.isHealthy()) {
continue;
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/HealthCheckType.java b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/HealthCheckType.java
index 53ee8539575..750f0b157b4 100644
--- a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/HealthCheckType.java
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/HealthCheckType.java
@@ -54,7 +54,7 @@ public enum HealthCheckType {
* In JDK 1.6, the map need full class for general. So ignore check style.
*/
@SuppressWarnings("checkstyle:linelength")
- private static final Map> EXTEND = new ConcurrentHashMap>();
+ private static final Map> EXTEND = new ConcurrentHashMap<>();
HealthCheckType(Class extends AbstractHealthChecker> healthCheckerClass) {
this.healthCheckerClass = healthCheckerClass;
@@ -90,7 +90,7 @@ public static Class extends AbstractHealthChecker> ofHealthCheckerClass(String
}
public static List> getLoadedHealthCheckerClasses() {
- List> all = new ArrayList>();
+ List> all = new ArrayList<>();
for (HealthCheckType type : values()) {
all.add(type.healthCheckerClass);
}
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/Http.java b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/Http.java
index 2b6fe2a1165..106b297f2e1 100644
--- a/api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/Http.java
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/Http.java
@@ -76,7 +76,7 @@ public Map getCustomHeaders() {
if (StringUtils.isBlank(headers)) {
return Collections.emptyMap();
}
- final Map headerMap = new HashMap(16);
+ final Map headerMap = new HashMap<>(16);
for (final String s : headers.split(Constants.NAMING_HTTP_HEADER_SPLITTER)) {
final String[] splits = s.split(":");
if (splits.length != 2) {
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/remote/NamingRemoteConstants.java b/api/src/main/java/com/alibaba/nacos/api/naming/remote/NamingRemoteConstants.java
index 7ee3b20d8a6..4eb9cccc30c 100644
--- a/api/src/main/java/com/alibaba/nacos/api/naming/remote/NamingRemoteConstants.java
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/remote/NamingRemoteConstants.java
@@ -26,6 +26,8 @@ public class NamingRemoteConstants {
public static final String REGISTER_INSTANCE = "registerInstance";
+ public static final String BATCH_REGISTER_INSTANCE = "batchRegisterInstance";
+
public static final String DE_REGISTER_INSTANCE = "deregisterInstance";
public static final String QUERY_SERVICE = "queryService";
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/remote/request/BatchInstanceRequest.java b/api/src/main/java/com/alibaba/nacos/api/naming/remote/request/BatchInstanceRequest.java
new file mode 100644
index 00000000000..01a67f92478
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/remote/request/BatchInstanceRequest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.api.naming.remote.request;
+
+import com.alibaba.nacos.api.naming.pojo.Instance;
+
+import java.util.List;
+
+/**
+ * The client registers multiple service instance request.
+ *
+ * @author chenhao26
+ */
+public class BatchInstanceRequest extends AbstractNamingRequest {
+
+ private String type;
+
+ /**
+ * save all service instance.
+ */
+ private List instances;
+
+ public BatchInstanceRequest() {
+ }
+
+ public BatchInstanceRequest(String namespace, String serviceName, String groupName, String type,
+ List instances) {
+ super(namespace, serviceName, groupName);
+ this.type = type;
+ this.instances = instances;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public List getInstances() {
+ return instances;
+ }
+
+ public void setInstances(List instances) {
+ this.instances = instances;
+ }
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/remote/response/BatchInstanceResponse.java b/api/src/main/java/com/alibaba/nacos/api/naming/remote/response/BatchInstanceResponse.java
new file mode 100644
index 00000000000..983941e2ba2
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/remote/response/BatchInstanceResponse.java
@@ -0,0 +1,40 @@
+/*
+ * 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.api.naming.remote.response;
+
+import com.alibaba.nacos.api.remote.response.Response;
+
+/**
+ * batch instance response.
+ *
+ * @author chenhao26
+ */
+public class BatchInstanceResponse extends Response {
+
+ private String type;
+
+ public BatchInstanceResponse() {
+ }
+
+ public BatchInstanceResponse(String type) {
+ this.type = type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/naming/utils/NamingUtils.java b/api/src/main/java/com/alibaba/nacos/api/naming/utils/NamingUtils.java
index 962903b8491..5106a89ad3c 100644
--- a/api/src/main/java/com/alibaba/nacos/api/naming/utils/NamingUtils.java
+++ b/api/src/main/java/com/alibaba/nacos/api/naming/utils/NamingUtils.java
@@ -21,6 +21,14 @@
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.utils.StringUtils;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import static com.alibaba.nacos.api.common.Constants.CLUSTER_NAME_PATTERN_STRING;
+import static com.alibaba.nacos.api.common.Constants.NUMBER_PATTERN_STRING;
+
/**
* NamingUtils.
*
@@ -29,6 +37,10 @@
*/
public class NamingUtils {
+ private static final Pattern CLUSTER_NAME_PATTERN = Pattern.compile(CLUSTER_NAME_PATTERN_STRING);
+
+ private static final Pattern NUMBER_PATTERN = Pattern.compile(NUMBER_PATTERN_STRING);
+
/**
* Returns a combined string with serviceName and groupName. serviceName can not be nil.
*
@@ -129,5 +141,45 @@ public static void checkInstanceIsLegal(Instance instance) throws NacosException
throw new NacosException(NacosException.INVALID_PARAM,
"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.");
}
+ if (!StringUtils.isEmpty(instance.getClusterName()) && !CLUSTER_NAME_PATTERN.matcher(instance.getClusterName()).matches()) {
+ throw new NacosException(NacosException.INVALID_PARAM,
+ String.format("Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: %s)",
+ instance.getClusterName()));
+ }
+ }
+
+ /**
+ * check batch register is Ephemeral.
+ * @param instance instance
+ * @throws NacosException NacosException
+ */
+ public static void checkInstanceIsEphemeral(Instance instance) throws NacosException {
+ if (!instance.isEphemeral()) {
+ throw new NacosException(NacosException.INVALID_PARAM,
+ String.format("Batch registration does not allow persistent instance registration , Instance:%s", instance));
+ }
+ }
+
+ /**
+ * Batch verify the validity of instances.
+ * @param instances List of instances to be registered
+ * @throws NacosException Nacos
+ */
+ public static void batchCheckInstanceIsLegal(List instances) throws NacosException {
+ Set newInstanceSet = new HashSet<>(instances);
+ for (Instance instance : newInstanceSet) {
+ checkInstanceIsEphemeral(instance);
+ checkInstanceIsLegal(instance);
+ }
+ }
+
+ /**
+ * Check string is a number or not.
+ *
+ * @param str a string of digits
+ * @return if it is a string of digits, return true
+ */
+ public static boolean isNumber(String str) {
+ return !StringUtils.isEmpty(str) && NUMBER_PATTERN.matcher(str).matches();
}
}
diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/RpcScheduledExecutor.java b/api/src/main/java/com/alibaba/nacos/api/remote/RpcScheduledExecutor.java
index 5d124d54f74..5fb8dd3b870 100644
--- a/api/src/main/java/com/alibaba/nacos/api/remote/RpcScheduledExecutor.java
+++ b/api/src/main/java/com/alibaba/nacos/api/remote/RpcScheduledExecutor.java
@@ -17,7 +17,6 @@
package com.alibaba.nacos.api.remote;
import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadFactory;
/**
* rpc scheduler executor .
@@ -34,12 +33,7 @@ public class RpcScheduledExecutor extends ScheduledThreadPoolExecutor {
"com.alibaba.nacos.remote.ServerCommonScheduler");
public RpcScheduledExecutor(int corePoolSize, final String threadName) {
- super(corePoolSize, new ThreadFactory() {
- @Override
- public Thread newThread(Runnable r) {
- return new Thread(r, threadName);
- }
- });
+ super(corePoolSize, r -> new Thread(r, threadName));
}
}
diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java
index 746908cabd2..56e94dad21f 100644
--- a/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java
+++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java
@@ -35,7 +35,7 @@ public class ConnectionSetupRequest extends InternalRequest {
private String tenant;
- private Map labels = new HashMap();
+ private Map labels = new HashMap<>();
public ConnectionSetupRequest() {
}
diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java
index 0376a22c289..82eba58db1b 100644
--- a/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java
+++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java
@@ -33,7 +33,7 @@ public class RequestMeta {
private String clientVersion = "";
- private Map labels = new HashMap();
+ private Map labels = new HashMap<>();
/**
* Getter method for property clientVersion.
diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/response/ErrorResponse.java b/api/src/main/java/com/alibaba/nacos/api/remote/response/ErrorResponse.java
index 2b4da45ba3a..1dc6dddaa12 100644
--- a/api/src/main/java/com/alibaba/nacos/api/remote/response/ErrorResponse.java
+++ b/api/src/main/java/com/alibaba/nacos/api/remote/response/ErrorResponse.java
@@ -16,6 +16,9 @@
package com.alibaba.nacos.api.remote.response;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
+
/**
* UnKnowResponse.
*
@@ -37,4 +40,24 @@ public static Response build(int errorCode, String msg) {
return response;
}
+ /**
+ * build an error response.
+ *
+ * @param exception exception
+ * @return response
+ */
+ public static Response build(Throwable exception) {
+ int errorCode;
+ if (exception instanceof NacosException) {
+ errorCode = ((NacosException) exception).getErrCode();
+ } else if (exception instanceof NacosRuntimeException) {
+ errorCode = ((NacosRuntimeException) exception).getErrCode();
+ } else {
+ errorCode = ResponseCode.FAIL.getCode();
+ }
+ ErrorResponse response = new ErrorResponse();
+ response.setErrorInfo(errorCode, exception.getMessage());
+ return response;
+ }
+
}
diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerLoaderInfoResponse.java b/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerLoaderInfoResponse.java
index 44d106ab2e8..e66f2e2034a 100644
--- a/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerLoaderInfoResponse.java
+++ b/api/src/main/java/com/alibaba/nacos/api/remote/response/ServerLoaderInfoResponse.java
@@ -29,7 +29,7 @@ public class ServerLoaderInfoResponse extends Response {
String address;
- Map loaderMetrics = new HashMap();
+ Map loaderMetrics = new HashMap<>();
public String getMetricsValue(String key) {
return loaderMetrics.get(key);
diff --git a/api/src/main/proto/nacos_grpc_service.proto b/api/src/main/proto/nacos_grpc_service.proto
index 797cce1d723..adf2a30a1d3 100644
--- a/api/src/main/proto/nacos_grpc_service.proto
+++ b/api/src/main/proto/nacos_grpc_service.proto
@@ -41,7 +41,7 @@ service Request {
}
service BiRequestStream {
- // Sends a commonRequest
+ // Sends a biStreamRequest
rpc requestBiStream (stream Payload) returns (stream Payload) {
}
}
diff --git a/api/src/test/java/com/alibaba/nacos/api/naming/pojo/InstanceTest.java b/api/src/test/java/com/alibaba/nacos/api/naming/pojo/InstanceTest.java
new file mode 100644
index 00000000000..7c43f7db193
--- /dev/null
+++ b/api/src/test/java/com/alibaba/nacos/api/naming/pojo/InstanceTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1999-2020 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.api.naming.pojo;
+
+import junit.framework.TestCase;
+import org.junit.Test;
+
+public class InstanceTest extends TestCase {
+
+ @Test
+ public void testCheckClusterNameFormat() {
+ Instance instance = new Instance();
+ instance.setClusterName("demo");
+ assertEquals("demo", instance.getClusterName());
+ }
+}
\ No newline at end of file
diff --git a/api/src/test/java/com/alibaba/nacos/api/naming/utils/NamingUtilsTest.java b/api/src/test/java/com/alibaba/nacos/api/naming/utils/NamingUtilsTest.java
index 627719174e9..38f74753f8d 100644
--- a/api/src/test/java/com/alibaba/nacos/api/naming/utils/NamingUtilsTest.java
+++ b/api/src/test/java/com/alibaba/nacos/api/naming/utils/NamingUtilsTest.java
@@ -16,10 +16,20 @@
package com.alibaba.nacos.api.naming.utils;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.PreservedMetadataKeys;
+import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.utils.StringUtils;
+import org.junit.Assert;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
public class NamingUtilsTest {
@@ -34,4 +44,126 @@ public void testGetGroupedNameOptional() {
String groupNameAndServiceName = NamingUtils.getGroupedNameOptional("serviceA", "groupA");
assertEquals("groupA@@serviceA", groupNameAndServiceName);
}
+
+ @Test
+ public void testCheckInstanceIsLegal() throws NacosException {
+ // check invalid clusterName
+ Instance instance = new Instance();
+ instance.setClusterName("cluster1,cluster2");
+ try {
+ NamingUtils.checkInstanceIsLegal(instance);
+ assertTrue(false);
+ } catch (Exception e) {
+ assertTrue(NacosException.class.equals(e.getClass()));
+ assertEquals(
+ "Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: cluster1,cluster2)",
+ e.getMessage());
+ }
+
+ // valid clusterName
+ instance.setClusterName("cluster1");
+ NamingUtils.checkInstanceIsLegal(instance);
+ assertTrue(true);
+
+ // check heartBeatTimeout, heartBeatInterval, ipDeleteTimeout
+ Map meta = new HashMap<>();
+ meta.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, "1");
+ meta.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, "2");
+ meta.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, "1");
+ instance.setMetadata(meta);
+ try {
+ NamingUtils.checkInstanceIsLegal(instance);
+ assertTrue(false);
+ } catch (Exception e) {
+ assertTrue(NacosException.class.equals(e.getClass()));
+ assertEquals(
+ "Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.",
+ e.getMessage());
+ }
+ meta.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, "3");
+ meta.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, "2");
+ meta.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, "3");
+ NamingUtils.checkInstanceIsLegal(instance);
+ assertTrue(true);
+ }
+
+ @Test
+ public void testBatchCheckInstanceIsLegal() throws NacosException {
+ // check invalid clusterName
+ Instance instance = new Instance();
+ instance.setClusterName("cluster1,cluster2");
+ List instanceList = new ArrayList<>();
+ instanceList.add(instance);
+ try {
+ NamingUtils.batchCheckInstanceIsLegal(instanceList);
+ assertTrue(false);
+ } catch (Exception e) {
+ assertTrue(NacosException.class.equals(e.getClass()));
+ assertEquals(
+ "Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: cluster1,cluster2)",
+ e.getMessage());
+ }
+ instanceList.remove(instance);
+
+ // TODO valid clusterName
+ instance.setClusterName("cluster1");
+ instanceList.add(instance);
+ NamingUtils.batchCheckInstanceIsLegal(instanceList);
+ assertTrue(true);
+
+ instanceList.remove(instance);
+
+ // check heartBeatTimeout, heartBeatInterval, ipDeleteTimeout
+ Map meta = new HashMap<>();
+ meta.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, "1");
+ meta.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, "2");
+ meta.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, "1");
+ instance.setMetadata(meta);
+ instanceList.add(instance);
+ try {
+ NamingUtils.batchCheckInstanceIsLegal(instanceList);
+ assertTrue(false);
+ } catch (Exception e) {
+ assertTrue(NacosException.class.equals(e.getClass()));
+ assertEquals(
+ "Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.",
+ e.getMessage());
+ }
+ instanceList.remove(instance);
+
+ meta.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, "3");
+ meta.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, "2");
+ meta.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, "3");
+ instance.setMetadata(meta);
+ instanceList.add(instance);
+ NamingUtils.batchCheckInstanceIsLegal(instanceList);
+ assertTrue(true);
+ }
+
+ @Test
+ public void testCheckInstanceIsEphemeral() throws NacosException {
+ Instance instance = new Instance();
+ instance.setIp("127.0.0.1");
+ instance.setPort(9089);
+ instance.setEphemeral(true);
+ NamingUtils.checkInstanceIsEphemeral(instance);
+ try {
+ instance = new Instance();
+ instance.setIp("127.0.0.1");
+ instance.setPort(9089);
+ instance.setEphemeral(false);
+ NamingUtils.checkInstanceIsEphemeral(instance);
+ } catch (NacosException e) {
+ Assert.assertEquals(e.getErrCode(), NacosException.INVALID_PARAM);
+ }
+ }
+
+ @Test
+ public void testIsNumber() {
+ String str1 = "abc";
+ assertTrue(!NamingUtils.isNumber(str1));
+
+ String str2 = "123456";
+ assertTrue(NamingUtils.isNumber(str2));
+ }
}
\ No newline at end of file
diff --git a/api/src/test/java/com/alibaba/nacos/api/remote/response/ErrorResponseTest.java b/api/src/test/java/com/alibaba/nacos/api/remote/response/ErrorResponseTest.java
new file mode 100644
index 00000000000..a5d5ea7a445
--- /dev/null
+++ b/api/src/test/java/com/alibaba/nacos/api/remote/response/ErrorResponseTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 1999-2020 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.api.remote.response;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ErrorResponseTest {
+
+ @Test
+ public void testBuildWithErrorCode() {
+ int errorCode = 500;
+ String msg = "err msg";
+
+ Response response = ErrorResponse.build(errorCode, msg);
+
+ Assert.assertEquals(errorCode, response.getErrorCode());
+ Assert.assertEquals(msg, response.getMessage());
+ }
+
+ @Test
+ public void testBuildWithThrowable() {
+ String errMsg = "exception msg";
+ RuntimeException runtimeException = new RuntimeException(errMsg);
+
+ Response response = ErrorResponse.build(runtimeException);
+
+ Assert.assertEquals(ResponseCode.FAIL.getCode(), response.getErrorCode());
+ Assert.assertEquals(errMsg, response.getMessage());
+ }
+
+ @Test
+ public void testBuildWithNacosException() {
+ int errCode = 500;
+ String errMsg = "nacos exception msg";
+ NacosException nacosException = new NacosException(errCode, errMsg);
+
+ Response response = ErrorResponse.build(nacosException);
+
+ Assert.assertEquals(errCode, response.getErrorCode());
+ Assert.assertEquals(errMsg, response.getMessage());
+ }
+
+ @Test
+ public void testBuildWithNacosRuntimeException() {
+ int errCode = 500;
+ String errMsg = "nacos runtime exception msg";
+ NacosRuntimeException nacosRuntimeException = new NacosRuntimeException(errCode, errMsg);
+
+ Response response = ErrorResponse.build(nacosRuntimeException);
+
+ Assert.assertEquals(errCode, response.getErrorCode());
+ Assert.assertEquals("errCode: " + errCode + ", errMsg: " + errMsg + " ", response.getMessage());
+ }
+
+}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/config/AuthConfigs.java b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthConfigs.java
index 5611a0caaf4..00ee7ba9722 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/config/AuthConfigs.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthConfigs.java
@@ -87,11 +87,9 @@ private void refreshPluginProperties() {
for (String each : properties.stringPropertyNames()) {
int typeIndex = each.indexOf('.');
String type = each.substring(0, typeIndex);
- if (!newProperties.containsKey(type)) {
- newProperties.put(type, new Properties());
- }
String subKey = each.substring(typeIndex + 1);
- newProperties.get(type).setProperty(subKey, properties.getProperty(each));
+ newProperties.computeIfAbsent(type, key -> new Properties())
+ .setProperty(subKey, properties.getProperty(each));
}
authPluginProperties = newProperties;
} catch (Exception e) {
diff --git a/client/pom.xml b/client/pom.xml
index 949a012afa6..7d606636c6d 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -113,11 +113,6 @@
org.apache.httpcomponents
httpasyncclient
-
- net.jcip
- jcip-annotations
- true
-
io.prometheus
diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/impl/process/HttpLoginProcessor.java b/client/src/main/java/com/alibaba/nacos/client/auth/impl/process/HttpLoginProcessor.java
index 5cafb05f3a9..c5b3827f9ef 100644
--- a/client/src/main/java/com/alibaba/nacos/client/auth/impl/process/HttpLoginProcessor.java
+++ b/client/src/main/java/com/alibaba/nacos/client/auth/impl/process/HttpLoginProcessor.java
@@ -67,8 +67,8 @@ public LoginIdentityContext getResponse(Properties properties) {
url = server + contextPath + LOGIN_URL;
}
- Map params = new HashMap(2);
- Map bodyMap = new HashMap(2);
+ Map params = new HashMap<>(2);
+ Map bodyMap = new HashMap<>(2);
params.put(PropertyKeyConst.USERNAME, properties.getProperty(PropertyKeyConst.USERNAME, StringUtils.EMPTY));
bodyMap.put(PropertyKeyConst.PASSWORD, properties.getProperty(PropertyKeyConst.PASSWORD, StringUtils.EMPTY));
try {
@@ -91,7 +91,7 @@ public LoginIdentityContext getResponse(Properties properties) {
}
return loginIdentityContext;
} catch (Exception e) {
- SECURITY_LOGGER.error("[ NacosClientAuthServiceImpl] login http request failed"
+ SECURITY_LOGGER.error("[NacosClientAuthServiceImpl] login http request failed"
+ " url: {}, params: {}, bodyMap: {}, errorMsg: {}", url, params, bodyMap, e.getMessage());
return null;
}
diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/CredentialService.java b/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/CredentialService.java
index da66bab211a..b49a848a8ee 100644
--- a/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/CredentialService.java
+++ b/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/CredentialService.java
@@ -31,7 +31,7 @@ public final class CredentialService implements SpasCredentialLoader {
private static final Logger LOGGER = LogUtils.logger(CredentialService.class);
- private static final ConcurrentHashMap INSTANCES = new ConcurrentHashMap();
+ private static final ConcurrentHashMap INSTANCES = new ConcurrentHashMap<>();
private final String appName;
diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjector.java b/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjector.java
index 8b176033fb1..7976eff769b 100644
--- a/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjector.java
+++ b/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjector.java
@@ -70,9 +70,7 @@ public void doInject(RequestResource resource, RamContext context, LoginIdentity
}
Map signHeaders = SpasAdapter
.getSignHeaders(getResource(resource.getNamespace(), resource.getGroup()), secretKey);
- if (signHeaders != null && !signHeaders.isEmpty()) {
- result.setParameters(signHeaders);
- }
+ result.setParameters(signHeaders);
}
private StsCredential getStsCredential() {
diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/ram/utils/SpasAdapter.java b/client/src/main/java/com/alibaba/nacos/client/auth/ram/utils/SpasAdapter.java
index 9a6b421d14b..d317053ead1 100644
--- a/client/src/main/java/com/alibaba/nacos/client/auth/ram/utils/SpasAdapter.java
+++ b/client/src/main/java/com/alibaba/nacos/client/auth/ram/utils/SpasAdapter.java
@@ -45,7 +45,7 @@ public class SpasAdapter {
private static final String SHA_ENCRYPT = "HmacSHA1";
public static Map getSignHeaders(String resource, String secretKey) {
- Map header = new HashMap(2);
+ Map header = new HashMap<>(2);
String timeStamp = String.valueOf(System.currentTimeMillis());
header.put(TIMESTAMP_HEADER, timeStamp);
if (secretKey != null) {
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java b/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java
index 9311262fbda..b196f300f32 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java
@@ -97,9 +97,21 @@ public String getConfig(String dataId, String group, long timeoutMs) throws Naco
@Override
public String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener)
throws NacosException {
- String content = getConfig(dataId, group, timeoutMs);
- worker.addTenantListenersWithContent(dataId, group, content, Arrays.asList(listener));
- return content;
+ group = StringUtils.isBlank(group) ? Constants.DEFAULT_GROUP : group.trim();
+ ConfigResponse configResponse = worker.getAgent()
+ .queryConfig(dataId, group, worker.getAgent().getTenant(), timeoutMs, false);
+ String content = configResponse.getContent();
+ String encryptedDataKey = configResponse.getEncryptedDataKey();
+ worker.addTenantListenersWithContent(dataId, group, content, encryptedDataKey, Arrays.asList(listener));
+
+ // get a decryptContent, fix https://github.com/alibaba/nacos/issues/7039
+ ConfigResponse cr = new ConfigResponse();
+ cr.setDataId(dataId);
+ cr.setGroup(group);
+ cr.setContent(content);
+ cr.setEncryptedDataKey(encryptedDataKey);
+ configFilterChainManager.doFilter(null, cr);
+ return cr.getContent();
}
@Override
@@ -148,7 +160,11 @@ private String getConfigInner(String tenant, String dataId, String group, long t
cr.setTenant(tenant);
cr.setGroup(group);
- // use local config first
+ // We first try to use local failover content if exists.
+ // A config content for failover is not created by client program automatically,
+ // but is maintained by user.
+ // This is designed for certain scenario like client emergency reboot,
+ // changing config needed in the same time, while nacos server is down.
String content = LocalConfigInfoProcessor.getFailover(worker.getAgentName(), dataId, group, tenant);
if (content != null) {
LOGGER.warn("[{}] [get-config] get failover ok, dataId={}, group={}, tenant={}, config={}",
@@ -177,13 +193,15 @@ private String getConfigInner(String tenant, String dataId, String group, long t
LOGGER.warn("[{}] [get-config] get from server error, dataId={}, group={}, tenant={}, msg={}",
worker.getAgentName(), dataId, group, tenant, ioe.toString());
}
-
- LOGGER.warn("[{}] [get-config] get snapshot ok, dataId={}, group={}, tenant={}, config={}",
- worker.getAgentName(), dataId, group, tenant, ContentUtils.truncateContent(content));
+
content = LocalConfigInfoProcessor.getSnapshot(worker.getAgentName(), dataId, group, tenant);
+ if (content != null) {
+ LOGGER.warn("[{}] [get-config] get snapshot ok, dataId={}, group={}, tenant={}, config={}",
+ worker.getAgentName(), dataId, group, tenant, ContentUtils.truncateContent(content));
+ }
cr.setContent(content);
String encryptedDataKey = LocalEncryptedDataKeyProcessor
- .getEncryptDataKeyFailover(agent.getName(), dataId, group, tenant);
+ .getEncryptDataKeySnapshot(agent.getName(), dataId, group, tenant);
cr.setEncryptedDataKey(encryptedDataKey);
configFilterChainManager.doFilter(null, cr);
content = cr.getContent();
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigContext.java b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigContext.java
index 74761586a09..142f51f67ff 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigContext.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigContext.java
@@ -28,7 +28,7 @@
*/
public class ConfigContext implements IConfigContext {
- private final Map param = new HashMap();
+ private final Map param = new HashMap<>();
@Override
public Object getParameter(String key) {
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequest.java b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequest.java
index 16b1d9a4eb2..404039276c6 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequest.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequest.java
@@ -36,7 +36,7 @@
*/
public class ConfigRequest implements IConfigRequest {
- private final Map param = new HashMap();
+ private final Map param = new HashMap<>();
private final IConfigContext configContext = new ConfigContext();
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponse.java b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponse.java
index 6644adee18a..c5d3e4735bb 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponse.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponse.java
@@ -36,7 +36,7 @@
*/
public class ConfigResponse implements IConfigResponse {
- private final Map param = new HashMap();
+ private final Map param = new HashMap<>();
private final IConfigContext configContext = new ConfigContext();
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/http/MetricsHttpAgent.java b/client/src/main/java/com/alibaba/nacos/client/config/http/MetricsHttpAgent.java
index af4d9017285..7c1e13a0340 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/http/MetricsHttpAgent.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/http/MetricsHttpAgent.java
@@ -21,6 +21,7 @@
import com.alibaba.nacos.common.http.HttpRestResult;
import io.prometheus.client.Histogram;
+import java.util.Date;
import java.util.Map;
/**
@@ -52,12 +53,14 @@ public void start() throws NacosException {
@Override
public HttpRestResult httpGet(String path, Map headers, Map paramValues,
String encode, long readTimeoutMs) throws Exception {
- Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor(GET, path, DEFAULT_CODE);
+ Date start = new Date();
+ Histogram.Child histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, DEFAULT_CODE);
HttpRestResult result;
try {
result = httpAgent.httpGet(path, headers, paramValues, encode, readTimeoutMs);
+ histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, String.valueOf(result.getCode()));
} finally {
- timer.observeDuration();
+ histogram.observe(System.currentTimeMillis() - start.getTime());
}
return result;
@@ -66,12 +69,14 @@ public HttpRestResult httpGet(String path, Map headers,
@Override
public HttpRestResult httpPost(String path, Map headers, Map paramValues,
String encode, long readTimeoutMs) throws Exception {
- Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor(POST, path, DEFAULT_CODE);
+ Date start = new Date();
+ Histogram.Child histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, DEFAULT_CODE);
HttpRestResult result;
try {
result = httpAgent.httpPost(path, headers, paramValues, encode, readTimeoutMs);
+ histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, String.valueOf(result.getCode()));
} finally {
- timer.observeDuration();
+ histogram.observe(System.currentTimeMillis() - start.getTime());
}
return result;
@@ -80,12 +85,14 @@ public HttpRestResult httpPost(String path, Map headers,
@Override
public HttpRestResult httpDelete(String path, Map headers, Map paramValues,
String encode, long readTimeoutMs) throws Exception {
- Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor(DELETE, path, DEFAULT_CODE);
+ Date start = new Date();
+ Histogram.Child histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, DEFAULT_CODE);
HttpRestResult result;
try {
result = httpAgent.httpDelete(path, headers, paramValues, encode, readTimeoutMs);
+ histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, String.valueOf(result.getCode()));
} finally {
- timer.observeDuration();
+ histogram.observe(System.currentTimeMillis() - start.getTime());
}
return result;
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java b/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java
index 471bb00f877..ae2d94473f5 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java
@@ -225,7 +225,8 @@ private String getUrl(String serverAddr, String relativePath) {
private boolean isFail(HttpRestResult result) {
return result.getCode() == HttpURLConnection.HTTP_INTERNAL_ERROR
|| result.getCode() == HttpURLConnection.HTTP_BAD_GATEWAY
- || result.getCode() == HttpURLConnection.HTTP_UNAVAILABLE;
+ || result.getCode() == HttpURLConnection.HTTP_UNAVAILABLE
+ || result.getCode() == HttpURLConnection.HTTP_NOT_FOUND;
}
public static String getAppname() {
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/AbstractConfigChangeParser.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/AbstractConfigChangeParser.java
index a7cd5ec705c..0e8596b791e 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/impl/AbstractConfigChangeParser.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/AbstractConfigChangeParser.java
@@ -42,7 +42,7 @@ public boolean isResponsibleFor(String type) {
}
protected Map filterChangeData(Map oldMap, Map newMap) {
- Map result = new HashMap(16);
+ Map result = new HashMap<>(16);
for (Map.Entry e : (Iterable>) oldMap.entrySet()) {
ConfigChangeItem cci;
if (newMap.containsKey(e.getKey())) {
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java
index 1bc230a190d..73868868828 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java
@@ -18,6 +18,7 @@
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.config.ConfigChangeEvent;
+import com.alibaba.nacos.api.config.ConfigChangeItem;
import com.alibaba.nacos.api.config.listener.AbstractSharedListener;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
@@ -134,7 +135,7 @@ public String getContent() {
public void setContent(String content) {
this.content = content;
- this.md5 = getMd5String(this.content);
+ this.md5 = getMd5String();
}
/**
@@ -168,13 +169,23 @@ public void setType(String type) {
*
* @param listener listener
*/
- public void addListener(Listener listener) {
+ public void addListener(Listener listener) throws NacosException {
if (null == listener) {
throw new IllegalArgumentException("listener is null");
}
- ManagerListenerWrap wrap =
- (listener instanceof AbstractConfigChangeListener) ? new ManagerListenerWrap(listener, md5, content)
- : new ManagerListenerWrap(listener, md5);
+ ManagerListenerWrap wrap;
+ if (listener instanceof AbstractConfigChangeListener) {
+ ConfigResponse cr = new ConfigResponse();
+ cr.setDataId(dataId);
+ cr.setGroup(group);
+ cr.setContent(content);
+ cr.setEncryptedDataKey(encryptedDataKey);
+ configFilterChainManager.doFilter(null, cr);
+ String contentTmp = cr.getContent();
+ wrap = new ManagerListenerWrap(listener, md5, contentTmp);
+ } else {
+ wrap = new ManagerListenerWrap(listener, md5);
+ }
if (listeners.addIfAbsent(wrap)) {
LOGGER.info("[{}] [add-listener] ok, tenant={}, dataId={}, group={}, cnt={}", name, tenant, dataId, group,
@@ -202,7 +213,7 @@ public void removeListener(Listener listener) {
* Returns the iterator on the listener list, read-only. It is guaranteed not to return NULL.
*/
public List getListeners() {
- List result = new ArrayList();
+ List result = new ArrayList<>();
for (ManagerListenerWrap wrap : listeners) {
result.add(wrap.listener);
}
@@ -317,11 +328,11 @@ private void safeNotifyListener(final String dataId, final String group, final S
listener.receiveConfigInfo(contentTmp);
// compare lastContent and content
if (listener instanceof AbstractConfigChangeListener) {
- Map data = ConfigChangeHandler.getInstance()
- .parseChangeData(listenerWrap.lastContent, content, type);
+ Map data = ConfigChangeHandler.getInstance()
+ .parseChangeData(listenerWrap.lastContent, contentTmp, type);
ConfigChangeEvent event = new ConfigChangeEvent(data);
((AbstractConfigChangeListener) listener).receiveConfigChange(event);
- listenerWrap.lastContent = content;
+ listenerWrap.lastContent = contentTmp;
}
listenerWrap.lastCallMd5 = md5;
@@ -331,8 +342,8 @@ private void safeNotifyListener(final String dataId, final String group, final S
LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} errCode={} errMsg={}", name,
dataId, group, md5, listener, ex.getErrCode(), ex.getErrMsg());
} catch (Throwable t) {
- LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} tx={}", name, dataId, group,
- md5, listener, t.getCause());
+ LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={}", name, dataId, group, md5,
+ listener, t);
} finally {
listenerWrap.inNotifying = false;
Thread.currentThread().setContextClassLoader(myClassLoader);
@@ -367,8 +378,8 @@ private void safeNotifyListener(final String dataId, final String group, final S
name, (finishNotify - startNotify), dataId, group, md5, listener);
}
- public static String getMd5String(String config) {
- return (null == config) ? Constants.NULL : MD5Utils.md5Hex(config, Constants.ENCODE);
+ public String getMd5String() {
+ return (null == content) ? Constants.NULL : MD5Utils.md5Hex(content, Constants.ENCODE);
}
private String loadCacheContentFromDiskLocal(String name, String dataId, String group, String tenant) {
@@ -392,21 +403,7 @@ public void setSyncWithServer(boolean syncWithServer) {
}
public CacheData(ConfigFilterChainManager configFilterChainManager, String name, String dataId, String group) {
- if (null == dataId || null == group) {
- throw new IllegalArgumentException("dataId=" + dataId + ", group=" + group);
- }
- this.name = name;
- this.configFilterChainManager = configFilterChainManager;
- this.dataId = dataId;
- this.group = group;
- this.tenant = TenantUtil.getUserTenantForAcm();
- listeners = new CopyOnWriteArrayList<>();
- this.isInitializing = true;
- if (initSnapshot) {
- this.content = loadCacheContentFromDiskLocal(name, dataId, group, tenant);
- this.md5 = getMd5String(content);
- }
- this.encryptedDataKey = loadEncryptedDataKeyFromDiskLocal(name, dataId, group, tenant);
+ this(configFilterChainManager, name, dataId, group, TenantUtil.getUserTenantForAcm());
}
public CacheData(ConfigFilterChainManager configFilterChainManager, String name, String dataId, String group,
@@ -414,16 +411,17 @@ public CacheData(ConfigFilterChainManager configFilterChainManager, String name,
if (null == dataId || null == group) {
throw new IllegalArgumentException("dataId=" + dataId + ", group=" + group);
}
- this.name = name;
this.configFilterChainManager = configFilterChainManager;
+ this.name = name;
this.dataId = dataId;
this.group = group;
this.tenant = tenant;
- listeners = new CopyOnWriteArrayList<>();
+ this.listeners = new CopyOnWriteArrayList<>();
this.isInitializing = true;
if (initSnapshot) {
this.content = loadCacheContentFromDiskLocal(name, dataId, group, tenant);
- this.md5 = getMd5String(content);
+ this.encryptedDataKey = loadEncryptedDataKeyFromDiskLocal(name, dataId, group, tenant);
+ this.md5 = getMd5String();
}
}
@@ -453,8 +451,11 @@ private static class ManagerListenerWrap {
final Listener listener;
- String lastCallMd5 = CacheData.getMd5String(null);
+ String lastCallMd5 = Constants.NULL;
+ /**
+ * here is a decryptContent.
+ */
String lastContent = null;
ManagerListenerWrap(Listener listener) {
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java
index 93e48522cf6..7cb69a8f1b3 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java
@@ -138,7 +138,7 @@ public class ClientWorker implements Closeable {
* @param group group of data
* @param listeners listeners
*/
- public void addListeners(String dataId, String group, List extends Listener> listeners) {
+ public void addListeners(String dataId, String group, List extends Listener> listeners) throws NacosException {
group = blank2defaultGroup(group);
CacheData cache = addCacheDataIfAbsent(dataId, group);
synchronized (cache) {
@@ -178,18 +178,20 @@ public void addTenantListeners(String dataId, String group, List extends Liste
/**
* Add listeners for tenant with content.
*
- * @param dataId dataId of data
- * @param group group of data
- * @param content content
- * @param listeners listeners
+ * @param dataId dataId of data
+ * @param group group of data
+ * @param content content
+ * @param encryptedDataKey encryptedDataKey
+ * @param listeners listeners
* @throws NacosException nacos exception
*/
- public void addTenantListenersWithContent(String dataId, String group, String content,
+ public void addTenantListenersWithContent(String dataId, String group, String content, String encryptedDataKey,
List extends Listener> listeners) throws NacosException {
group = blank2defaultGroup(group);
String tenant = agent.getTenant();
CacheData cache = addCacheDataIfAbsent(dataId, group, tenant);
synchronized (cache) {
+ cache.setEncryptedDataKey(encryptedDataKey);
cache.setContent(content);
for (Listener listener : listeners) {
cache.addListener(listener);
@@ -362,6 +364,7 @@ public CacheData addCacheDataIfAbsent(String dataId, String group, String tenant
// fix issue # 1317
if (enableRemoteSyncConfig) {
ConfigResponse response = getServerConfig(dataId, group, tenant, 3000L, false);
+ cache.setEncryptedDataKey(response.getEncryptedDataKey());
cache.setContent(response.getContent());
}
}
@@ -432,8 +435,8 @@ private void refreshContentAndCheck(CacheData cacheData, boolean notify) {
try {
ConfigResponse response = getServerConfig(cacheData.dataId, cacheData.group, cacheData.tenant, 3000L,
notify);
- cacheData.setContent(response.getContent());
cacheData.setEncryptedDataKey(response.getEncryptedDataKey());
+ cacheData.setContent(response.getContent());
if (null != response.getConfigType()) {
cacheData.setType(response.getConfigType());
}
@@ -521,7 +524,7 @@ private void setHealthServer(boolean isHealthServer) {
public class ConfigRpcTransportClient extends ConfigTransportClient {
- private final BlockingQueue