diff --git a/README.md b/README.md
index 625eb068440..67ce034542e 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
Nacos (official site: [nacos.io](https://nacos.io)) is an easy-to-use platform designed for dynamic service discovery and configuration and service management. It helps you to build cloud native applications and microservices platform easily.
-Service is a first-class citizen in Nacos. Nacos supports almost all type of services,for example,[Dubbo/gRPC service](https://nacos.io/en-us/docs/use-nacos-with-dubbo.html), [Spring Cloud RESTFul service](https://nacos.io/en-us/docs/use-nacos-with-springcloud.html) or [Kubernetes service](https://nacos.io/en-us/docs/use-nacos-with-kubernetes.html).
+Service is a first-class citizen in Nacos. Nacos supports almost all type of services,for example,[Dubbo/gRPC service](https://nacos.io/docs/latest/ecology/use-nacos-with-dubbo/), [Spring Cloud RESTFul service](https://nacos.io/docs/latest/ecology/use-nacos-with-spring-cloud/) or [Kubernetes service](https://nacos.io/docs/latest/quickstart/quick-start-kubernetes/).
Nacos provides four major functions.
@@ -68,23 +68,23 @@ On the **Windows** platform, run the following command to start server with stan
startup.cmd -m standalone
```
-For more details, see [quick-start.](https://nacos.io/en-us/docs/quick-start.html)
+For more details, see [quick-start.](https://nacos.io/docs/latest/quickstart/quick-start/)
## Quick start for other open-source projects:
-* [Quick start with Nacos command and console](https://nacos.io/en-us/docs/quick-start.html)
+* [Quick start with Nacos command and console](https://nacos.io/docs/latest/quickstart/quick-start/)
-* [Quick start with dubbo](https://nacos.io/en-us/docs/use-nacos-with-dubbo.html)
+* [Quick start with dubbo](https://nacos.io/docs/latest/ecology/use-nacos-with-dubbo/)
-* [Quick start with spring cloud](https://nacos.io/en-us/docs/quick-start-spring-cloud.html)
+* [Quick start with spring cloud](https://nacos.io/docs/latest/ecology/use-nacos-with-spring-cloud/)
-* [Quick start with kubernetes](https://nacos.io/en-us/docs/use-nacos-with-kubernetes.html)
+* [Quick start with kubernetes](https://nacos.io/docs/latest/quickstart/quick-start-kubernetes/)
## Documentation
-You can view the full documentation from the [Nacos website](https://nacos.io/en-us/docs/v2/what-is-nacos.html).
+You can view the full documentation from the [Nacos website](https://nacos.io/docs/latest/overview/).
-You can also read this online eBook from the [NACOS ARCHITECTURE & PRINCIPLES](https://www.yuque.com/nacos/ebook/kbyo6n).
+You can also read this online eBook from the [NACOS ARCHITECTURE & PRINCIPLES](https://nacos.io/docs/ebook/kbyo6n/).
All the latest and long-term notice can also be found here from [GitHub notice issue](https://github.com/alibaba/nacos/labels/notice).
diff --git a/api/pom.xml b/api/pom.xml
index 7ddee1459d3..6d31744932e 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -100,6 +100,5 @@
javax.annotationjavax.annotation-api
-
diff --git a/api/src/main/java/com/alibaba/nacos/api/NacosFactory.java b/api/src/main/java/com/alibaba/nacos/api/NacosFactory.java
index 33c9e25e906..88b224e5a71 100644
--- a/api/src/main/java/com/alibaba/nacos/api/NacosFactory.java
+++ b/api/src/main/java/com/alibaba/nacos/api/NacosFactory.java
@@ -19,6 +19,8 @@
import com.alibaba.nacos.api.config.ConfigFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.lock.LockService;
+import com.alibaba.nacos.api.lock.NacosLockFactory;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingMaintainFactory;
import com.alibaba.nacos.api.naming.NamingMaintainService;
@@ -98,4 +100,15 @@ public static NamingMaintainService createMaintainService(String serverAddr) thr
public static NamingMaintainService createMaintainService(Properties properties) throws NacosException {
return NamingMaintainFactory.createMaintainService(properties);
}
+
+ /**
+ * Create lock service.
+ *
+ * @param properties init param
+ * @return lock service
+ * @throws NacosException Exception
+ */
+ public static LockService createLockService(Properties properties) throws NacosException {
+ return NacosLockFactory.createLockService(properties);
+ }
}
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 b3313dd45e8..c8acd6336a3 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
@@ -35,6 +35,8 @@ public class Constants {
public static final String CLIENT_VERSION_KEY = "ClientVersion";
+ public static final String CLIENT_IP = "ClientIp";
+
public static final String UNKNOWN_APP = "UnknownApp";
public static final String DEFAULT_DOMAINNAME = "commonconfig.config-host.taobao.com";
@@ -274,6 +276,15 @@ public static class Naming {
public static final String CMDB_CONTEXT_TYPE = "CMDB";
}
+ /**
+ * The constants in lock directory.
+ */
+ public static class Lock {
+
+ public static final String LOCK_MODULE = "lock";
+
+ }
+
/**
* The constants in remote directory.
*/
diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequest.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequest.java
index c9dab7288f6..557dc29c286 100644
--- a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequest.java
+++ b/api/src/main/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequest.java
@@ -25,14 +25,16 @@
* @version $Id: ConfigChangeClusterSyncRequest.java, v 0.1 2020年08月11日 4:30 PM liuzunfei Exp $
*/
public class ConfigChangeClusterSyncRequest extends AbstractConfigRequest {
-
- String tag;
-
+
long lastModified;
+ String grayName;
+
+ @Deprecated
boolean isBeta;
- boolean isBatch;
+ @Deprecated
+ String tag;
public boolean isBeta() {
return isBeta;
@@ -42,14 +44,6 @@ public void setBeta(boolean beta) {
isBeta = beta;
}
- public boolean isBatch() {
- return isBatch;
- }
-
- public void setBatch(boolean batch) {
- isBatch = batch;
- }
-
/**
* Getter method for property tag.
*
@@ -68,6 +62,14 @@ public void setTag(String tag) {
this.tag = tag;
}
+ public String getGrayName() {
+ return grayName;
+ }
+
+ public void setGrayName(String grayName) {
+ this.grayName = grayName;
+ }
+
/**
* Getter method for property lastModified.
*
diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponse.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponse.java
index 6b417fd6711..d92f273ed62 100644
--- a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponse.java
+++ b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponse.java
@@ -30,6 +30,8 @@ public class ConfigQueryResponse extends Response {
public static final int CONFIG_QUERY_CONFLICT = 400;
+ public static final int NO_RIGHT = 403;
+
String content;
String encryptedDataKey;
diff --git a/api/src/main/java/com/alibaba/nacos/api/lock/LockService.java b/api/src/main/java/com/alibaba/nacos/api/lock/LockService.java
new file mode 100644
index 00000000000..589c5c9d8f9
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/lock/LockService.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1999-2023 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.lock;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.lock.model.LockInstance;
+
+import java.util.Properties;
+
+/**
+ * Nacos Lock Process.
+ *
+ *
lock => {@link LockService#lock(LockInstance)} -> {@link LockInstance#lock(LockService)} ->
+ * {@link LockService#remoteTryLock(LockInstance)} unLock => {@link LockService#unLock(LockInstance)} ->
+ * {@link LockInstance#unLock(LockService)} -> {@link LockService#remoteReleaseLock(LockInstance)}
+ *
+ * @author 985492783@qq.com
+ * @date 2023/8/24 19:49
+ */
+public interface LockService {
+
+ /**
+ * Real lock method expose to user to acquire the lock. It will call {@link LockInstance#lock(LockService)}
+ *
+ *
+ * @param instance instance
+ * @return Boolean
+ * @throws NacosException NacosException
+ */
+ Boolean lock(LockInstance instance) throws NacosException;
+
+ /**
+ * Real lock method expose to user to release the lock. It will call {@link LockInstance#unLock(LockService)}
+ *
+ *
+ * @param instance instance
+ * @return Boolean
+ * @throws NacosException NacosException
+ */
+ Boolean unLock(LockInstance instance) throws NacosException;
+
+ /**
+ * use grpc request to try lock.
+ *
+ * @param instance instance
+ * @return Boolean
+ * @throws NacosException NacosException
+ */
+ Boolean remoteTryLock(LockInstance instance) throws NacosException;
+
+ /**
+ * use grpc request to release lock.
+ *
+ * @param instance instance
+ * @return Boolean
+ * @throws NacosException NacosException
+ */
+ Boolean remoteReleaseLock(LockInstance instance) throws NacosException;
+
+ /**
+ * get properties.
+ *
+ * @return Properties
+ */
+ Properties getProperties();
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/lock/NacosLockFactory.java b/api/src/main/java/com/alibaba/nacos/api/lock/NacosLockFactory.java
new file mode 100644
index 00000000000..82a97a1a3cd
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/lock/NacosLockFactory.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1999-2023 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.lock;
+
+import com.alibaba.nacos.api.exception.NacosException;
+
+import java.lang.reflect.Constructor;
+import java.util.Properties;
+
+/**
+ * lock Factory.
+ *
+ * @author 985492783@qq.com
+ * @date 2023/8/25 0:40
+ */
+public class NacosLockFactory {
+
+ /**
+ * Create a new lock service.
+ *
+ * @param properties lock service properties
+ * @return new lock service
+ * @throws NacosException nacos exception
+ */
+ public static LockService createLockService(Properties properties) throws NacosException {
+ try {
+ Class> driverImplClass = Class.forName("com.alibaba.nacos.client.lock.NacosLockService");
+ Constructor constructor = driverImplClass.getConstructor(Properties.class);
+ return (LockService) constructor.newInstance(properties);
+ } catch (Throwable e) {
+ throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
+ }
+ }
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/lock/common/LockConstants.java b/api/src/main/java/com/alibaba/nacos/api/lock/common/LockConstants.java
new file mode 100644
index 00000000000..af4c8de0bc6
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/lock/common/LockConstants.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1999-2023 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.lock.common;
+
+/**
+ * lock constant.
+ *
+ * @author 985492783@qq.com
+ * @date 2023/8/23 15:53
+ */
+public class LockConstants {
+
+ public static final String NACOS_LOCK_TYPE = "NACOS_LOCK";
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/lock/constant/PropertyConstants.java b/api/src/main/java/com/alibaba/nacos/api/lock/constant/PropertyConstants.java
new file mode 100644
index 00000000000..dccfd1fd8e7
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/lock/constant/PropertyConstants.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2023 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.lock.constant;
+
+/**
+ * lock properties constants.
+ * @author 985492783@qq.com
+ * @description PropertyConstants
+ * @date 2023/6/28 17:38
+ */
+public class PropertyConstants {
+ public static final String LOCK_REQUEST_TIMEOUT = "lockRequestTimeout";
+
+ public static final String LOCK_DEFAULT_WAIT_TIME = "nacos.lock.default_wait_time";
+
+ public static final Long LOCK_DEFAULT_WAIT_SECOND = 10_000L;
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/lock/model/LockInstance.java b/api/src/main/java/com/alibaba/nacos/api/lock/model/LockInstance.java
new file mode 100644
index 00000000000..95f0866d082
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/lock/model/LockInstance.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 1999-2023 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.lock.model;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.lock.LockService;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * lock info entity.
+ *
+ * @author 985492783@qq.com
+ * @date 2023/6/28 2:46
+ */
+public class LockInstance implements Serializable {
+
+ private static final long serialVersionUID = -3460985546826875524L;
+
+ private String key;
+
+ private Long expiredTime;
+
+ private Map params;
+
+ private String lockType;
+
+ public LockInstance(String key, Long expiredTime, String lockType) {
+ this.key = key;
+ this.expiredTime = expiredTime;
+ this.lockType = lockType;
+ }
+
+ public LockInstance() {
+ }
+
+ public Long getExpiredTime() {
+ return expiredTime;
+ }
+
+ public void setExpiredTime(Long expiredTime) {
+ this.expiredTime = expiredTime;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public Map getParams() {
+ return params;
+ }
+
+ public void setParams(Map params) {
+ this.params = params;
+ }
+
+ /**
+ * Will call {@link LockService#remoteTryLock(LockInstance)} request grpc to get lock and do something. can be
+ * {@link Override} to do some client special logic.
+ *
+ * @param lockService {@link LockService}
+ * @return Boolean {@link Boolean}
+ * @throws NacosException NacosException
+ */
+ public Boolean lock(LockService lockService) throws NacosException {
+ return lockService.remoteTryLock(this);
+ }
+
+ /**
+ * Will call {@link LockService#remoteReleaseLock(LockInstance)} request grpc to release lock and do something.
+ * can be {@link Override} to do some client special logic.
+ *
+ * @param lockService {@link LockService}
+ * @return Boolean {@link Boolean}
+ * @throws NacosException NacosException
+ */
+ public Boolean unLock(LockService lockService) throws NacosException {
+ return lockService.remoteReleaseLock(this);
+ }
+
+ /**
+ * spi get lock type.
+ *
+ * @return type
+ */
+ public String getLockType() {
+ return lockType;
+ }
+
+ public void setLockType(String lockType) {
+ this.lockType = lockType;
+ }
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/lock/remote/AbstractLockRequest.java b/api/src/main/java/com/alibaba/nacos/api/lock/remote/AbstractLockRequest.java
new file mode 100644
index 00000000000..22e15396f42
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/lock/remote/AbstractLockRequest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 1999-2023 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.lock.remote;
+
+import com.alibaba.nacos.api.remote.request.Request;
+
+import static com.alibaba.nacos.api.common.Constants.Lock.LOCK_MODULE;
+
+/**
+ * lock grpc request.
+ *
+ * @author 985492783@qq.com
+ * @description LockRequest
+ * @date 2023/6/29 12:00
+ */
+public abstract class AbstractLockRequest extends Request {
+
+ @Override
+ public String getModule() {
+ return LOCK_MODULE;
+ }
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/lock/remote/LockOperationEnum.java b/api/src/main/java/com/alibaba/nacos/api/lock/remote/LockOperationEnum.java
new file mode 100644
index 00000000000..b2f64008424
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/lock/remote/LockOperationEnum.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1999-2023 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.lock.remote;
+
+import java.io.Serializable;
+
+/**
+ * lock operation.
+ * @author 985492783@qq.com
+ */
+public enum LockOperationEnum implements Serializable {
+
+ /**
+ * Acquire.
+ */
+ ACQUIRE,
+ /**
+ * Release.
+ */
+ RELEASE,
+ /**
+ * Expire.
+ */
+ EXPIRE;
+
+ private static final long serialVersionUID = -241044344531890549L;
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/lock/remote/request/LockOperationRequest.java b/api/src/main/java/com/alibaba/nacos/api/lock/remote/request/LockOperationRequest.java
new file mode 100644
index 00000000000..777aa835537
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/lock/remote/request/LockOperationRequest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 1999-2023 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.lock.remote.request;
+
+import com.alibaba.nacos.api.lock.model.LockInstance;
+import com.alibaba.nacos.api.lock.remote.AbstractLockRequest;
+import com.alibaba.nacos.api.lock.remote.LockOperationEnum;
+
+/**
+ * grpc acquire lock request.
+ *
+ * @author 985492783@qq.com
+ * @description AcquireLockRequest
+ * @date 2023/6/29 12:01
+ */
+public class LockOperationRequest extends AbstractLockRequest {
+
+ private LockInstance lockInstance;
+
+ private LockOperationEnum lockOperationEnum;
+
+ public LockInstance getLockInstance() {
+ return lockInstance;
+ }
+
+ public void setLockInstance(LockInstance lockInstance) {
+ this.lockInstance = lockInstance;
+ }
+
+ public LockOperationEnum getLockOperationEnum() {
+ return lockOperationEnum;
+ }
+
+ public void setLockOperationEnum(LockOperationEnum lockOperationEnum) {
+ this.lockOperationEnum = lockOperationEnum;
+ }
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/lock/remote/response/LockOperationResponse.java b/api/src/main/java/com/alibaba/nacos/api/lock/remote/response/LockOperationResponse.java
new file mode 100644
index 00000000000..bafdc83cb90
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/lock/remote/response/LockOperationResponse.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 1999-2023 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.lock.remote.response;
+
+import com.alibaba.nacos.api.remote.response.Response;
+import com.alibaba.nacos.api.remote.response.ResponseCode;
+
+/**
+ * grpc acquire lock response.
+ *
+ * @author 985492783@qq.com
+ * @description AcquireLockResponse
+ * @date 2023/6/29 13:51
+ */
+public class LockOperationResponse extends Response {
+
+ private Object result;
+
+ public LockOperationResponse() {
+
+ }
+
+ public LockOperationResponse(Boolean result) {
+ this.result = result;
+ }
+
+ /**
+ * create success response.
+ * @param result result
+ * @return LockOperationResponse
+ */
+ public static LockOperationResponse success(Boolean result) {
+ LockOperationResponse response = new LockOperationResponse(result);
+ return response;
+ }
+
+ /**
+ * create fail response.
+ * @param message message
+ * @return LockOperationResponse
+ */
+ public static LockOperationResponse fail(String message) {
+ LockOperationResponse response = new LockOperationResponse(false);
+ response.setResultCode(ResponseCode.FAIL.getCode());
+ response.setMessage(message);
+ return response;
+ }
+
+ public Object getResult() {
+ return result;
+ }
+
+ public void setResult(Object result) {
+ this.result = result;
+ }
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java b/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java
index 53b4c35735f..4ee3ee2e188 100644
--- a/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java
+++ b/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java
@@ -90,6 +90,26 @@ public enum ErrorCode {
*/
PARAMETER_MISMATCH(20009, "parameter mismatch"),
+ /**
+ * config gray request error.
+ */
+ CONFIG_GRAY_OVER_MAX_VERSION_COUNT(20010, "config gray version version over max count"),
+
+ /**
+ * config gray tag v2 rule format invalid.
+ */
+ CONFIG_GRAY_RULE_FORMAT_INVALID(20011, "config gray rule format invalid"),
+
+ /**
+ * config gray tag v2 rule version invalid.
+ */
+ CONFIG_GRAY_VERSION_INVALID(20012, "config gray rule version invalid"),
+
+ /**
+ * config gray request error.
+ */
+ CONFIG_GRAY_NAME_UNRECOGNIZED_ERROR(20013, "config gray name not recognized"),
+
/**
* service name error.
*/
@@ -183,7 +203,25 @@ public enum ErrorCode {
/**
* server error.
*/
- SERVER_ERROR(30000, "server error");
+ SERVER_ERROR(30000, "server error"),
+
+ /**
+ * API will be deprecated.
+ */
+ API_DEPRECATED(40000, "API deprecated."),
+
+ /**
+ * Config use 100001 ~ 100999.
+ **/
+ METADATA_ILLEGAL(100002, "导入的元数据非法"),
+
+ DATA_VALIDATION_FAILED(100003, "未读取到合法数据"),
+
+ PARSING_DATA_FAILED(100004, "解析数据失败"),
+
+ DATA_EMPTY(100005, "导入的文件数据为空"),
+
+ NO_SELECTED_CONFIG(100006, "没有选择任何配置");
private final Integer code;
diff --git a/api/src/main/java/com/alibaba/nacos/api/model/v2/Result.java b/api/src/main/java/com/alibaba/nacos/api/model/v2/Result.java
index 98ae78c5f73..183fa8a4555 100644
--- a/api/src/main/java/com/alibaba/nacos/api/model/v2/Result.java
+++ b/api/src/main/java/com/alibaba/nacos/api/model/v2/Result.java
@@ -96,6 +96,17 @@ public static Result failure(ErrorCode errorCode, T data) {
return new Result<>(errorCode.getCode(), errorCode.getMsg(), data);
}
+ /**
+ * Failed return with code, message and data.
+ * @param data type
+ * @param code error code
+ * @param msg error message
+ * @return Result
+ */
+ public static Result failure(Integer code, String msg, T data) {
+ return new Result<>(code, msg, data);
+ }
+
@Override
public String toString() {
return "Result{" + "errorCode=" + code + ", message='" + message + '\'' + ", data=" + data + '}';
diff --git a/api/src/main/java/com/alibaba/nacos/api/model/v2/SupportedLanguage.java b/api/src/main/java/com/alibaba/nacos/api/model/v2/SupportedLanguage.java
new file mode 100644
index 00000000000..8ca862cef5f
--- /dev/null
+++ b/api/src/main/java/com/alibaba/nacos/api/model/v2/SupportedLanguage.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1999-2024 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.model.v2;
+
+/**
+ * Supported languages for announcements.
+ *
+ * @author zhangyukun on:2024/9/24
+ */
+public enum SupportedLanguage {
+ /**
+ * Chinese language.
+ */
+ ZH_CN("zh-CN"),
+
+ /**
+ * English language.
+ */
+ EN_US("en-US");
+
+ private final String language;
+
+ SupportedLanguage(String language) {
+ this.language = language;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ /**
+ * Check if the given language is supported.
+ *
+ * @param language the language to check
+ * @return true if the language is supported, false otherwise
+ */
+ public static boolean isSupported(String language) {
+ for (SupportedLanguage lang : SupportedLanguage.values()) {
+ if (lang.getLanguage().equals(language)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/RemoteConstants.java b/api/src/main/java/com/alibaba/nacos/api/remote/RemoteConstants.java
index a5b22ffc2b4..904af67ec38 100644
--- a/api/src/main/java/com/alibaba/nacos/api/remote/RemoteConstants.java
+++ b/api/src/main/java/com/alibaba/nacos/api/remote/RemoteConstants.java
@@ -40,4 +40,6 @@ public class RemoteConstants {
public static final String LABEL_MODULE_NAMING = "naming";
public static final String MONITOR_LABEL_NONE = "none";
+
+ public static final String LABEL_MODULE_LOCK = "lock";
}
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 c633f893484..221e90cb7df 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
@@ -18,9 +18,11 @@
import com.alibaba.nacos.api.ability.constant.AbilityKey;
import com.alibaba.nacos.api.ability.constant.AbilityStatus;
+import com.alibaba.nacos.api.common.Constants;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
/**
* RequestMeta info.
@@ -38,6 +40,8 @@ public class RequestMeta {
private Map labels = new HashMap<>();
+ private Map appLabels = new HashMap<>();
+
private Map abilityTable;
public AbilityStatus getConnectionAbility(AbilityKey abilityKey) {
@@ -90,6 +94,35 @@ public Map getLabels() {
*/
public void setLabels(Map labels) {
this.labels = labels;
+ extractAppLabels();
+ }
+
+ private void extractAppLabels() {
+ HashMap applabelsMap = new HashMap(8) {
+ {
+ put(Constants.APPNAME, labels.get(Constants.APPNAME));
+ put(Constants.CLIENT_VERSION_KEY, clientVersion);
+ put(Constants.CLIENT_IP, clientIp);
+ }
+ };
+ labels.entrySet().stream().filter(Objects::nonNull).filter(e -> e.getKey().startsWith(Constants.APP_CONN_PREFIX)
+ && e.getKey().length() > Constants.APP_CONN_PREFIX.length() && !e.getValue().trim().isEmpty())
+ .forEach(entry -> {
+ applabelsMap.putIfAbsent(entry.getKey().substring(Constants.APP_CONN_PREFIX.length()),
+ entry.getValue());
+ });
+ this.appLabels = applabelsMap;
+ }
+
+ /**
+ * get labels map with filter of starting with prefix #{@link Constants#APP_CONN_PREFIX} and return a new map trim
+ * the prefix #{@link Constants#APP_CONN_PREFIX}.
+ *
+ * @return map of labels.
+ * @date 2024/2/29
+ */
+ public Map getAppLabels() {
+ return appLabels;
}
/**
diff --git a/api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload b/api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload
index cbd1e87502a..618f0a47132 100644
--- a/api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload
+++ b/api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload
@@ -57,4 +57,6 @@ com.alibaba.nacos.api.naming.remote.response.InstanceResponse
com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse
com.alibaba.nacos.api.naming.remote.response.QueryServiceResponse
com.alibaba.nacos.api.naming.remote.response.ServiceListResponse
-com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse
\ No newline at end of file
+com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse
+com.alibaba.nacos.api.lock.remote.request.LockOperationRequest
+com.alibaba.nacos.api.lock.remote.response.LockOperationResponse
diff --git a/api/src/test/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequestTest.java b/api/src/test/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequestTest.java
index d1055c18c73..6562f54dee7 100644
--- a/api/src/test/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequestTest.java
+++ b/api/src/test/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequestTest.java
@@ -40,7 +40,6 @@ void before() {
configChangeClusterSyncRequest.setTag(TAG);
configChangeClusterSyncRequest.setBeta(Boolean.TRUE);
configChangeClusterSyncRequest.setLastModified(0L);
- configChangeClusterSyncRequest.setBatch(false);
configChangeClusterSyncRequest.putAllHeader(HEADERS);
requestId = injectRequestUuId(configChangeClusterSyncRequest);
}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/AbstractProtocolAuthService.java b/auth/src/main/java/com/alibaba/nacos/auth/AbstractProtocolAuthService.java
index 150738db186..50bc4e765c0 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/AbstractProtocolAuthService.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/AbstractProtocolAuthService.java
@@ -17,8 +17,13 @@
package com.alibaba.nacos.auth;
import com.alibaba.nacos.auth.annotation.Secured;
-import com.alibaba.nacos.auth.config.AuthConfigs;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentity;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentityChecker;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentityCheckerHolder;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;
import com.alibaba.nacos.auth.util.Loggers;
+import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.api.Permission;
import com.alibaba.nacos.plugin.auth.api.Resource;
@@ -40,28 +45,36 @@
*/
public abstract class AbstractProtocolAuthService implements ProtocolAuthService {
- protected final AuthConfigs authConfigs;
+ protected final NacosAuthConfig authConfig;
- protected AbstractProtocolAuthService(AuthConfigs authConfigs) {
- this.authConfigs = authConfigs;
+ protected final ServerIdentityChecker checker;
+
+ protected AbstractProtocolAuthService(NacosAuthConfig authConfig) {
+ this.authConfig = authConfig;
+ this.checker = ServerIdentityCheckerHolder.getInstance().getChecker();
+ }
+
+ @Override
+ public void initialize() {
+ this.checker.init(authConfig);
}
@Override
public boolean enableAuth(Secured secured) {
Optional authPluginService = AuthPluginManager.getInstance()
- .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());
+ .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());
if (authPluginService.isPresent()) {
return authPluginService.get().enableAuth(secured.action(), secured.signType());
}
Loggers.AUTH.warn("Can't find auth plugin for type {}, please add plugin to classpath or set {} as false",
- authConfigs.getNacosAuthSystemType(), Constants.Auth.NACOS_CORE_AUTH_ENABLED);
+ authConfig.getNacosAuthSystemType(), Constants.Auth.NACOS_CORE_AUTH_ENABLED);
return false;
}
@Override
public boolean validateIdentity(IdentityContext identityContext, Resource resource) throws AccessException {
Optional authPluginService = AuthPluginManager.getInstance()
- .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());
+ .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());
if (authPluginService.isPresent()) {
return authPluginService.get().validateIdentity(identityContext, resource);
}
@@ -71,13 +84,37 @@ public boolean validateIdentity(IdentityContext identityContext, Resource resour
@Override
public boolean validateAuthority(IdentityContext identityContext, Permission permission) throws AccessException {
Optional authPluginService = AuthPluginManager.getInstance()
- .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());
+ .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());
if (authPluginService.isPresent()) {
return authPluginService.get().validateAuthority(identityContext, permission);
}
return true;
}
+ @Override
+ public ServerIdentityResult checkServerIdentity(R request, Secured secured) {
+ if (isInvalidServerIdentity()) {
+ return ServerIdentityResult.fail(
+ "Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`"
+ + " and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`");
+ }
+ ServerIdentity serverIdentity = parseServerIdentity(request);
+ return checker.check(serverIdentity, secured);
+ }
+
+ private boolean isInvalidServerIdentity() {
+ return StringUtils.isBlank(authConfig.getServerIdentityKey()) || StringUtils.isBlank(
+ authConfig.getServerIdentityValue());
+ }
+
+ /**
+ * Parse server identity from protocol request.
+ *
+ * @param request protocol request
+ * @return nacos server identity.
+ */
+ protected abstract ServerIdentity parseServerIdentity(R request);
+
/**
* Get resource from secured annotation specified resource.
*
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/GrpcProtocolAuthService.java b/auth/src/main/java/com/alibaba/nacos/auth/GrpcProtocolAuthService.java
index 7b4c3197931..7f0ae736880 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/GrpcProtocolAuthService.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/GrpcProtocolAuthService.java
@@ -18,16 +18,19 @@
import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.auth.annotation.Secured;
-import com.alibaba.nacos.plugin.auth.api.IdentityContext;
-import com.alibaba.nacos.plugin.auth.api.Resource;
-import com.alibaba.nacos.auth.config.AuthConfigs;
-import com.alibaba.nacos.plugin.auth.constant.SignType;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
import com.alibaba.nacos.auth.context.GrpcIdentityContextBuilder;
import com.alibaba.nacos.auth.parser.grpc.AbstractGrpcResourceParser;
import com.alibaba.nacos.auth.parser.grpc.ConfigGrpcResourceParser;
import com.alibaba.nacos.auth.parser.grpc.NamingGrpcResourceParser;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentity;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;
import com.alibaba.nacos.auth.util.Loggers;
import com.alibaba.nacos.common.utils.StringUtils;
+import com.alibaba.nacos.plugin.auth.api.IdentityContext;
+import com.alibaba.nacos.plugin.auth.api.Resource;
+import com.alibaba.nacos.plugin.auth.constant.ApiType;
+import com.alibaba.nacos.plugin.auth.constant.SignType;
import java.util.HashMap;
import java.util.Map;
@@ -43,14 +46,15 @@ public class GrpcProtocolAuthService extends AbstractProtocolAuthService(2);
- identityContextBuilder = new GrpcIdentityContextBuilder(authConfigs);
+ identityContextBuilder = new GrpcIdentityContextBuilder(authConfig);
}
@Override
public void initialize() {
+ super.initialize();
resourceParserMap.put(SignType.NAMING, new NamingGrpcResourceParser());
resourceParserMap.put(SignType.CONFIG, new ConfigGrpcResourceParser());
}
@@ -73,4 +77,19 @@ public Resource parseResource(Request request, Secured secured) {
public IdentityContext parseIdentity(Request request) {
return identityContextBuilder.build(request);
}
+
+ @Override
+ public ServerIdentityResult checkServerIdentity(Request request, Secured secured) {
+ if (ApiType.INNER_API != secured.apiType()) {
+ return ServerIdentityResult.noMatched();
+ }
+ return super.checkServerIdentity(request, secured);
+ }
+
+ @Override
+ protected ServerIdentity parseServerIdentity(Request request) {
+ String serverIdentityKey = authConfig.getServerIdentityKey();
+ String serverIdentity = request.getHeader(serverIdentityKey);
+ return new ServerIdentity(serverIdentityKey, serverIdentity);
+ }
}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/HttpProtocolAuthService.java b/auth/src/main/java/com/alibaba/nacos/auth/HttpProtocolAuthService.java
index 3d6507246db..47fb9a41131 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/HttpProtocolAuthService.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/HttpProtocolAuthService.java
@@ -17,16 +17,17 @@
package com.alibaba.nacos.auth;
import com.alibaba.nacos.auth.annotation.Secured;
-import com.alibaba.nacos.plugin.auth.api.IdentityContext;
-import com.alibaba.nacos.plugin.auth.api.Resource;
-import com.alibaba.nacos.auth.config.AuthConfigs;
-import com.alibaba.nacos.plugin.auth.constant.SignType;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
import com.alibaba.nacos.auth.context.HttpIdentityContextBuilder;
import com.alibaba.nacos.auth.parser.http.AbstractHttpResourceParser;
import com.alibaba.nacos.auth.parser.http.ConfigHttpResourceParser;
import com.alibaba.nacos.auth.parser.http.NamingHttpResourceParser;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentity;
import com.alibaba.nacos.auth.util.Loggers;
import com.alibaba.nacos.common.utils.StringUtils;
+import com.alibaba.nacos.plugin.auth.api.IdentityContext;
+import com.alibaba.nacos.plugin.auth.api.Resource;
+import com.alibaba.nacos.plugin.auth.constant.SignType;
import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
@@ -43,14 +44,15 @@ public class HttpProtocolAuthService extends AbstractProtocolAuthService(2);
- identityContextBuilder = new HttpIdentityContextBuilder(authConfigs);
+ identityContextBuilder = new HttpIdentityContextBuilder(authConfig);
}
@Override
public void initialize() {
+ super.initialize();
resourceParserMap.put(SignType.NAMING, new NamingHttpResourceParser());
resourceParserMap.put(SignType.CONFIG, new ConfigHttpResourceParser());
}
@@ -72,4 +74,11 @@ public Resource parseResource(HttpServletRequest request, Secured secured) {
public IdentityContext parseIdentity(HttpServletRequest request) {
return identityContextBuilder.build(request);
}
+
+ @Override
+ protected ServerIdentity parseServerIdentity(HttpServletRequest request) {
+ String serverIdentityKey = authConfig.getServerIdentityKey();
+ String serverIdentity = request.getHeader(serverIdentityKey);
+ return new ServerIdentity(serverIdentityKey, serverIdentity);
+ }
}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java b/auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java
index 0815db4d224..f2f99366931 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java
@@ -17,6 +17,7 @@
package com.alibaba.nacos.auth;
import com.alibaba.nacos.auth.annotation.Secured;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.api.Permission;
import com.alibaba.nacos.plugin.auth.api.Resource;
@@ -85,4 +86,13 @@ public interface ProtocolAuthService {
* @throws AccessException exception during validating
*/
boolean validateAuthority(IdentityContext identityContext, Permission permission) throws AccessException;
+
+ /**
+ * check server identity.
+ *
+ * @param request protocol request
+ * @param secured secured api secured annotation
+ * @return server identity result
+ */
+ ServerIdentityResult checkServerIdentity(R request, Secured secured);
}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/annotation/Secured.java b/auth/src/main/java/com/alibaba/nacos/auth/annotation/Secured.java
index c1c0fe24f4b..5c3548c16b1 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/annotation/Secured.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/annotation/Secured.java
@@ -16,6 +16,7 @@
package com.alibaba.nacos.auth.annotation;
+import com.alibaba.nacos.plugin.auth.constant.ApiType;
import com.alibaba.nacos.auth.parser.DefaultResourceParser;
import com.alibaba.nacos.auth.parser.ResourceParser;
import com.alibaba.nacos.common.utils.StringUtils;
@@ -70,4 +71,12 @@
* @return tags
*/
String[] tags() default {};
+
+ /**
+ * The type of API. Distinguishing between ADMIN_API and OPEN_API.
+ *
+ * @return the type of the API
+ */
+ ApiType apiType() default ApiType.OPEN_API;
+
}
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 35375143b7e..7c3c7de838b 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
@@ -58,11 +58,17 @@ public class AuthConfigs extends Subscriber {
private static Boolean cachingEnabled = null;
/**
- * Whether auth enabled.
+ * Whether server auth enabled.
*/
@Value("${" + Constants.Auth.NACOS_CORE_AUTH_ENABLED + ":false}")
private boolean authEnabled;
+ /**
+ * Whether console auth enabled.
+ */
+ @Value("${" + Constants.Auth.NACOS_CORE_AUTH_CONSOLE_ENABLED + ":true}")
+ private boolean consoleAuthEnabled;
+
/**
* Which auth system is in use.
*/
@@ -75,9 +81,6 @@ public class AuthConfigs extends Subscriber {
@Value("${" + Constants.Auth.NACOS_CORE_AUTH_SERVER_IDENTITY_VALUE + ":}")
private String serverIdentityValue;
- @Value("${" + Constants.Auth.NACOS_CORE_AUTH_ENABLE_USER_AGENT_AUTH_WHITE + ":false}")
- private boolean enableUserAgentAuthWhite;
-
private boolean hasGlobalAdminRole;
private Map authPluginProperties = new HashMap<>();
@@ -94,7 +97,7 @@ public AuthConfigs() {
*/
@PostConstruct
public void validate() throws NacosException {
- if (!authEnabled) {
+ if (!authEnabled && !consoleAuthEnabled) {
return;
}
if (StringUtils.isEmpty(nacosAuthSystemType)) {
@@ -147,19 +150,24 @@ public String getServerIdentityValue() {
return serverIdentityValue;
}
- public boolean isEnableUserAgentAuthWhite() {
- return enableUserAgentAuthWhite;
+ /**
+ * console auth function is open.
+ *
+ * @return console auth function is open
+ */
+ public boolean isConsoleAuthEnabled() {
+ return consoleAuthEnabled;
}
/**
- * auth function is open.
+ * server auth function is open.
*
- * @return auth function is open
+ * @return server auth function is open
*/
public boolean isAuthEnabled() {
return authEnabled;
}
-
+
/**
* Whether permission information can be cached.
*
@@ -189,11 +197,10 @@ public static void setCachingEnabled(boolean cachingEnabled) {
public void onEvent(ServerConfigChangeEvent event) {
try {
authEnabled = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_ENABLED, Boolean.class, false);
+ consoleAuthEnabled = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_CONSOLE_ENABLED, Boolean.class, true);
cachingEnabled = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_CACHING_ENABLED, Boolean.class, true);
serverIdentityKey = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SERVER_IDENTITY_KEY, "");
serverIdentityValue = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SERVER_IDENTITY_VALUE, "");
- enableUserAgentAuthWhite = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_ENABLE_USER_AGENT_AUTH_WHITE,
- Boolean.class, false);
nacosAuthSystemType = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SYSTEM_TYPE, "");
refreshPluginProperties();
ModuleStateHolder.getInstance().getModuleState(AuthModuleStateBuilder.AUTH_MODULE)
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/config/AuthErrorCode.java b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthErrorCode.java
index 85e846f8172..4e2f27e3619 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/config/AuthErrorCode.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthErrorCode.java
@@ -27,10 +27,10 @@ public enum AuthErrorCode {
* invalid auth type.
*/
INVALID_TYPE(50001,
- "Invalid auth type, Please set `nacos.core.auth.system.type`, detail: https://nacos.io/zh-cn/docs/v2/plugin/auth-plugin.html"),
+ "Invalid auth type, Please set `nacos.core.auth.system.type`, detail: https://nacos.io/docs/latest/manual/admin/auth/"),
EMPTY_IDENTITY(50002,
- "Empty identity, Please set `nacos.core.auth.server.identity.key` and `nacos.core.auth.server.identity.value`, detail: https://nacos.io/zh-cn/docs/v2/guide/user/auth.html");
+ "Empty identity, Please set `nacos.core.auth.server.identity.key` and `nacos.core.auth.server.identity.value`, detail: https://nacos.io/docs/latest/manual/admin/auth/");
private final Integer code;
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilder.java b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilder.java
index b6eb66657ce..079fb732ba5 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilder.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilder.java
@@ -47,7 +47,7 @@ public class AuthModuleStateBuilder implements ModuleStateBuilder {
public ModuleState build() {
ModuleState result = new ModuleState(AUTH_MODULE);
AuthConfigs authConfigs = ApplicationUtils.getBean(AuthConfigs.class);
- result.newState(AUTH_ENABLED, authConfigs.isAuthEnabled());
+ result.newState(AUTH_ENABLED, authConfigs.isConsoleAuthEnabled());
result.newState(LOGIN_PAGE_ENABLED, isLoginPageEnabled(authConfigs));
result.newState(AUTH_SYSTEM_TYPE, authConfigs.getNacosAuthSystemType());
result.newState(AUTH_ADMIN_REQUEST, isAdminRequest(authConfigs));
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/config/NacosAuthConfig.java b/auth/src/main/java/com/alibaba/nacos/auth/config/NacosAuthConfig.java
new file mode 100644
index 00000000000..c133786aa18
--- /dev/null
+++ b/auth/src/main/java/com/alibaba/nacos/auth/config/NacosAuthConfig.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1999-2023 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.auth.config;
+
+/**
+ * Nacos Auth configurations.
+ *
+ * @author xiweng.yy
+ */
+public interface NacosAuthConfig {
+
+ /**
+ * Whether nacos server or console auth enabled.
+ *
+ * @return {@code true} means enabled, otherwise {@code false}
+ */
+ boolean isAuthEnabled();
+
+ /**
+ * Get current auth plugin type.
+ *
+ * @return auth plugin type.
+ */
+ String getNacosAuthSystemType();
+
+ /**
+ * Whether support server identity to identify request from other nacos servers.
+ *
+ * @return {@code true} means supported, otherwise {@code false}
+ */
+ boolean isSupportServerIdentity();
+
+ /**
+ * Get server identity key.
+ *
+ * @return server identity key If {@link #isSupportServerIdentity()} return {@code true}, otherwise empty string.
+ */
+ String getServerIdentityKey();
+
+ /**
+ * Get server identity value.
+ *
+ * @return server identity value If {@link #isSupportServerIdentity()} return {@code true}, otherwise empty string.
+ */
+ String getServerIdentityValue();
+}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilder.java b/auth/src/main/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilder.java
index bfa3af6303c..0247a1f3137 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilder.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilder.java
@@ -17,7 +17,7 @@
package com.alibaba.nacos.auth.context;
import com.alibaba.nacos.api.remote.request.Request;
-import com.alibaba.nacos.auth.config.AuthConfigs;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.constant.Constants;
import com.alibaba.nacos.plugin.auth.spi.server.AuthPluginManager;
@@ -35,10 +35,10 @@
*/
public class GrpcIdentityContextBuilder implements IdentityContextBuilder {
- private final AuthConfigs authConfigs;
+ private final NacosAuthConfig authConfig;
- public GrpcIdentityContextBuilder(AuthConfigs authConfigs) {
- this.authConfigs = authConfigs;
+ public GrpcIdentityContextBuilder(NacosAuthConfig authConfig) {
+ this.authConfig = authConfig;
}
/**
@@ -51,7 +51,7 @@ public GrpcIdentityContextBuilder(AuthConfigs authConfigs) {
@Override
public IdentityContext build(Request request) {
Optional authPluginService = AuthPluginManager.getInstance()
- .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());
+ .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());
IdentityContext result = new IdentityContext();
getRemoteIp(request, result);
if (!authPluginService.isPresent()) {
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/context/HttpIdentityContextBuilder.java b/auth/src/main/java/com/alibaba/nacos/auth/context/HttpIdentityContextBuilder.java
index 0571c7f9e1c..92760391afd 100644
--- a/auth/src/main/java/com/alibaba/nacos/auth/context/HttpIdentityContextBuilder.java
+++ b/auth/src/main/java/com/alibaba/nacos/auth/context/HttpIdentityContextBuilder.java
@@ -16,7 +16,7 @@
package com.alibaba.nacos.auth.context;
-import com.alibaba.nacos.auth.config.AuthConfigs;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.constant.Constants;
@@ -40,10 +40,10 @@ public class HttpIdentityContextBuilder implements IdentityContextBuilder authPluginService = AuthPluginManager.getInstance()
- .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());
+ .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());
if (!authPluginService.isPresent()) {
return result;
}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/DefaultChecker.java b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/DefaultChecker.java
new file mode 100644
index 00000000000..6403f858e86
--- /dev/null
+++ b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/DefaultChecker.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1999-2023 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.auth.serveridentity;
+
+import com.alibaba.nacos.auth.annotation.Secured;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
+
+/**
+ * Nacos default server identity checker.
+ *
+ * @author xiweng.yy
+ */
+public class DefaultChecker implements ServerIdentityChecker {
+
+ private NacosAuthConfig authConfig;
+
+ @Override
+ public void init(NacosAuthConfig authConfigs) {
+ this.authConfig = authConfigs;
+ }
+
+ @Override
+ public ServerIdentityResult check(ServerIdentity serverIdentity, Secured secured) {
+ if (authConfig.getServerIdentityValue().equals(serverIdentity.getIdentityValue())) {
+ return ServerIdentityResult.success();
+ }
+ return ServerIdentityResult.noMatched();
+ }
+}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentity.java b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentity.java
new file mode 100644
index 00000000000..2c846e3f87d
--- /dev/null
+++ b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1999-2023 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.auth.serveridentity;
+
+/**
+ * Nacos server identity.
+ *
+ * @author xiweng.yy
+ */
+public class ServerIdentity {
+
+ private final String identityKey;
+
+ private final String identityValue;
+
+ public ServerIdentity(String identityKey, String identityValue) {
+ this.identityKey = identityKey;
+ this.identityValue = identityValue;
+ }
+
+ public String getIdentityKey() {
+ return identityKey;
+ }
+
+ public String getIdentityValue() {
+ return identityValue;
+ }
+}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityChecker.java b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityChecker.java
new file mode 100644
index 00000000000..3cb13268f73
--- /dev/null
+++ b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityChecker.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1999-2023 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.auth.serveridentity;
+
+import com.alibaba.nacos.auth.annotation.Secured;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
+
+/**
+ * Nacos server identity checker for nacos inner/admin API identity check.
+ *
+ * @author xiweng.yy
+ */
+public interface ServerIdentityChecker {
+
+ /**
+ * Do init checker.
+ *
+ * @param authConfig config for nacos auth.
+ */
+ void init(NacosAuthConfig authConfig);
+
+ /**
+ * Do check nacos server identity.
+ *
+ * @param serverIdentity server identity
+ * @param secured secured api secured annotation
+ * @return result of checking server identity
+ */
+ ServerIdentityResult check(ServerIdentity serverIdentity, Secured secured);
+}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityCheckerHolder.java b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityCheckerHolder.java
new file mode 100644
index 00000000000..77469df5e32
--- /dev/null
+++ b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityCheckerHolder.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 1999-2023 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.auth.serveridentity;
+
+import com.alibaba.nacos.common.spi.NacosServiceLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+
+/**
+ * Server Identity Checker SPI holder.
+ *
+ * @author xiweng.yy
+ */
+public class ServerIdentityCheckerHolder {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ServerIdentityCheckerHolder.class);
+
+ private static final ServerIdentityCheckerHolder INSTANCE = new ServerIdentityCheckerHolder();
+
+ private ServerIdentityChecker checker;
+
+ private ServerIdentityCheckerHolder() {
+ tryGetCheckerBySpi();
+ }
+
+ public static ServerIdentityCheckerHolder getInstance() {
+ return INSTANCE;
+ }
+
+ public ServerIdentityChecker getChecker() {
+ return checker;
+ }
+
+ private synchronized void tryGetCheckerBySpi() {
+ Collection checkers = NacosServiceLoader.load(ServerIdentityChecker.class);
+ if (checkers.isEmpty()) {
+ checker = new DefaultChecker();
+ LOGGER.info("Not found ServerIdentityChecker implementation from SPI, use default.");
+ return;
+ }
+ if (checkers.size() > 1) {
+ checker = showAllImplementations(checkers);
+ return;
+ }
+ checker = checkers.iterator().next();
+ LOGGER.info("Found ServerIdentityChecker implementation {}", checker.getClass().getCanonicalName());
+ }
+
+ private ServerIdentityChecker showAllImplementations(Collection checkers) {
+ ServerIdentityChecker result = checkers.iterator().next();
+ for (ServerIdentityChecker each : checkers) {
+ LOGGER.warn("Found ServerIdentityChecker implementation {}", each.getClass().getCanonicalName());
+ }
+ LOGGER.warn("Found more than one ServerIdentityChecker implementation from SPI, use the first one {}.",
+ result.getClass().getCanonicalName());
+ return result;
+ }
+}
diff --git a/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityResult.java b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityResult.java
new file mode 100644
index 00000000000..68093d24f07
--- /dev/null
+++ b/auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityResult.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 1999-2023 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.auth.serveridentity;
+
+/**
+ * Nacos server identity check result.
+ *
+ * @author xiweng.yy
+ */
+public class ServerIdentityResult {
+
+ private final ResultStatus status;
+
+ private final String message;
+
+ private ServerIdentityResult(ResultStatus status, String message) {
+ this.status = status;
+ this.message = message;
+ }
+
+ public ResultStatus getStatus() {
+ return status;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public static ServerIdentityResult success() {
+ return new ServerIdentityResult(ResultStatus.MATCHED, "Server identity matched.");
+ }
+
+ public static ServerIdentityResult noMatched() {
+ return new ServerIdentityResult(ResultStatus.NOT_MATCHED, "Server identity not matched.");
+ }
+
+ public static ServerIdentityResult fail(String message) {
+ return new ServerIdentityResult(ResultStatus.FAIL, message);
+ }
+
+ public enum ResultStatus {
+
+ /**
+ * Nacos server identity matched.
+ */
+ MATCHED,
+
+ /**
+ * Nacos server identity not matched, need authentication.
+ */
+ NOT_MATCHED,
+
+ /**
+ * Nacos server identity check failed.
+ */
+ FAIL;
+ }
+}
diff --git a/auth/src/test/java/com/alibaba/nacos/auth/GrpcProtocolAuthServiceTest.java b/auth/src/test/java/com/alibaba/nacos/auth/GrpcProtocolAuthServiceTest.java
index b9a937d1833..a14a300ffe4 100644
--- a/auth/src/test/java/com/alibaba/nacos/auth/GrpcProtocolAuthServiceTest.java
+++ b/auth/src/test/java/com/alibaba/nacos/auth/GrpcProtocolAuthServiceTest.java
@@ -19,12 +19,14 @@
import com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;
import com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest;
import com.alibaba.nacos.auth.annotation.Secured;
-import com.alibaba.nacos.auth.config.AuthConfigs;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
import com.alibaba.nacos.auth.mock.MockAuthPluginService;
import com.alibaba.nacos.auth.mock.MockResourceParser;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.api.Permission;
import com.alibaba.nacos.plugin.auth.api.Resource;
+import com.alibaba.nacos.plugin.auth.constant.ApiType;
import com.alibaba.nacos.plugin.auth.constant.SignType;
import com.alibaba.nacos.plugin.auth.exception.AccessException;
import org.junit.jupiter.api.BeforeEach;
@@ -41,12 +43,13 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class GrpcProtocolAuthServiceTest {
@Mock
- private AuthConfigs authConfigs;
+ private NacosAuthConfig authConfig;
private ConfigPublishRequest configRequest;
@@ -56,7 +59,7 @@ class GrpcProtocolAuthServiceTest {
@BeforeEach
void setUp() throws Exception {
- protocolAuthService = new GrpcProtocolAuthService(authConfigs);
+ protocolAuthService = new GrpcProtocolAuthService(authConfig);
protocolAuthService.initialize();
mockConfigRequest();
mockNamingRequest();
@@ -144,7 +147,7 @@ void testValidateIdentityWithoutPlugin() throws AccessException {
@Test
void testValidateIdentityWithPlugin() throws AccessException {
- Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
+ Mockito.when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
IdentityContext identityContext = new IdentityContext();
assertFalse(protocolAuthService.validateIdentity(identityContext, Resource.EMPTY_RESOURCE));
}
@@ -157,7 +160,7 @@ void testValidateAuthorityWithoutPlugin() throws AccessException {
@Test
void testValidateAuthorityWithPlugin() throws AccessException {
- Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
+ Mockito.when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
assertFalse(protocolAuthService.validateAuthority(new IdentityContext(),
new Permission(Resource.EMPTY_RESOURCE, "")));
}
@@ -165,7 +168,7 @@ void testValidateAuthorityWithPlugin() throws AccessException {
@Test
@Secured(signType = SignType.CONFIG)
void testEnabledAuthWithPlugin() throws NoSuchMethodException {
- Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
+ Mockito.when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
Secured secured = getMethodSecure("testEnabledAuthWithPlugin");
assertTrue(protocolAuthService.enableAuth(secured));
}
@@ -173,11 +176,61 @@ void testEnabledAuthWithPlugin() throws NoSuchMethodException {
@Test
@Secured(signType = SignType.CONFIG)
void testEnabledAuthWithoutPlugin() throws NoSuchMethodException {
- Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn("non-exist-plugin");
+ Mockito.when(authConfig.getNacosAuthSystemType()).thenReturn("non-exist-plugin");
Secured secured = getMethodSecure("testEnabledAuthWithoutPlugin");
assertFalse(protocolAuthService.enableAuth(secured));
}
+ @Test
+ @Secured(apiType = ApiType.INNER_API)
+ void testCheckServerIdentityWithoutIdentityConfig() throws NoSuchMethodException {
+ Secured secured = getMethodSecure("testCheckServerIdentityWithoutIdentityConfig");
+ ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.FAIL, result.getStatus());
+ assertEquals("Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`"
+ + " and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`",
+ result.getMessage());
+ when(authConfig.getServerIdentityKey()).thenReturn("1");
+ result = protocolAuthService.checkServerIdentity(namingRequest, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.FAIL, result.getStatus());
+ assertEquals("Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`"
+ + " and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`",
+ result.getMessage());
+ }
+
+ @Test
+ @Secured(apiType = ApiType.INNER_API)
+ void testCheckServerIdentityNotMatched() throws NoSuchMethodException {
+ Secured secured = getMethodSecure("testCheckServerIdentityNotMatched");
+ when(authConfig.getServerIdentityKey()).thenReturn("1");
+ when(authConfig.getServerIdentityValue()).thenReturn("2");
+ ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());
+ namingRequest.putHeader("1", "3");
+ result = protocolAuthService.checkServerIdentity(namingRequest, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());
+ }
+
+ @Test
+ @Secured(apiType = ApiType.INNER_API)
+ void testCheckServerIdentityMatched() throws NoSuchMethodException {
+ when(authConfig.getServerIdentityKey()).thenReturn("1");
+ when(authConfig.getServerIdentityValue()).thenReturn("2");
+ namingRequest.putHeader("1", "2");
+ Secured secured = getMethodSecure("testCheckServerIdentityMatched");
+ ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.MATCHED, result.getStatus());
+ }
+
+ @Test
+ @Secured
+ void testCheckServerIdentityForOtherTypeApi() throws NoSuchMethodException {
+ namingRequest.putHeader("1", "2");
+ Secured secured = getMethodSecure("testCheckServerIdentityForOtherTypeApi");
+ ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());
+ }
+
private Secured getMethodSecure(String methodName) throws NoSuchMethodException {
Method method = GrpcProtocolAuthServiceTest.class.getDeclaredMethod(methodName);
return method.getAnnotation(Secured.class);
diff --git a/auth/src/test/java/com/alibaba/nacos/auth/HttpProtocolAuthServiceTest.java b/auth/src/test/java/com/alibaba/nacos/auth/HttpProtocolAuthServiceTest.java
index e5e4ae7045c..d10e214e2a7 100644
--- a/auth/src/test/java/com/alibaba/nacos/auth/HttpProtocolAuthServiceTest.java
+++ b/auth/src/test/java/com/alibaba/nacos/auth/HttpProtocolAuthServiceTest.java
@@ -19,9 +19,10 @@
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.CommonParams;
import com.alibaba.nacos.auth.annotation.Secured;
-import com.alibaba.nacos.auth.config.AuthConfigs;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
import com.alibaba.nacos.auth.mock.MockAuthPluginService;
import com.alibaba.nacos.auth.mock.MockResourceParser;
+import com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.api.Permission;
import com.alibaba.nacos.plugin.auth.api.Resource;
@@ -31,7 +32,6 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@@ -45,6 +45,7 @@
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
// todo remove this
@@ -52,7 +53,7 @@
class HttpProtocolAuthServiceTest {
@Mock
- private AuthConfigs authConfigs;
+ private NacosAuthConfig authConfig;
@Mock
private HttpServletRequest request;
@@ -61,14 +62,14 @@ class HttpProtocolAuthServiceTest {
@BeforeEach
void setUp() throws Exception {
- protocolAuthService = new HttpProtocolAuthService(authConfigs);
+ protocolAuthService = new HttpProtocolAuthService(authConfig);
protocolAuthService.initialize();
- Mockito.when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn("testNNs");
- Mockito.when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn("testNG");
- Mockito.when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn("testS");
- Mockito.when(request.getParameter(eq("tenant"))).thenReturn("testCNs");
- Mockito.when(request.getParameter(eq(Constants.GROUP))).thenReturn("testCG");
- Mockito.when(request.getParameter(eq(Constants.DATA_ID))).thenReturn("testD");
+ when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn("testNNs");
+ when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn("testNG");
+ when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn("testS");
+ when(request.getParameter(eq("tenant"))).thenReturn("testCNs");
+ when(request.getParameter(eq(Constants.GROUP))).thenReturn("testCG");
+ when(request.getParameter(eq(Constants.DATA_ID))).thenReturn("testD");
}
@Test
@@ -139,7 +140,7 @@ void testValidateIdentityWithoutPlugin() throws AccessException {
@Test
void testValidateIdentityWithPlugin() throws AccessException {
- Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
+ when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
IdentityContext identityContext = new IdentityContext();
assertFalse(protocolAuthService.validateIdentity(identityContext, Resource.EMPTY_RESOURCE));
}
@@ -152,7 +153,7 @@ void testValidateAuthorityWithoutPlugin() throws AccessException {
@Test
void testValidateAuthorityWithPlugin() throws AccessException {
- Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
+ when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
assertFalse(protocolAuthService.validateAuthority(new IdentityContext(),
new Permission(Resource.EMPTY_RESOURCE, "")));
}
@@ -160,7 +161,7 @@ void testValidateAuthorityWithPlugin() throws AccessException {
@Test
@Secured(signType = SignType.CONFIG)
void testEnabledAuthWithPlugin() throws NoSuchMethodException {
- Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
+ when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
Secured secured = getMethodSecure("testEnabledAuthWithPlugin");
assertTrue(protocolAuthService.enableAuth(secured));
}
@@ -168,11 +169,49 @@ void testEnabledAuthWithPlugin() throws NoSuchMethodException {
@Test
@Secured(signType = SignType.CONFIG)
void testEnabledAuthWithoutPlugin() throws NoSuchMethodException {
- Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn("non-exist-plugin");
+ when(authConfig.getNacosAuthSystemType()).thenReturn("non-exist-plugin");
Secured secured = getMethodSecure("testEnabledAuthWithoutPlugin");
assertFalse(protocolAuthService.enableAuth(secured));
}
+ @Test
+ void testCheckServerIdentityWithoutIdentityConfig() throws NoSuchMethodException {
+ Secured secured = getMethodSecure("testCheckServerIdentityWithoutIdentityConfig");
+ ServerIdentityResult result = protocolAuthService.checkServerIdentity(request, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.FAIL, result.getStatus());
+ assertEquals("Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`"
+ + " and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`",
+ result.getMessage());
+ when(authConfig.getServerIdentityKey()).thenReturn("1");
+ result = protocolAuthService.checkServerIdentity(request, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.FAIL, result.getStatus());
+ assertEquals("Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`"
+ + " and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`",
+ result.getMessage());
+ }
+
+ @Test
+ void testCheckServerIdentityNotMatched() throws NoSuchMethodException {
+ Secured secured = getMethodSecure("testCheckServerIdentityNotMatched");
+ when(authConfig.getServerIdentityKey()).thenReturn("1");
+ when(authConfig.getServerIdentityValue()).thenReturn("2");
+ ServerIdentityResult result = protocolAuthService.checkServerIdentity(request, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());
+ when(request.getHeader("1")).thenReturn("3");
+ result = protocolAuthService.checkServerIdentity(request, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());
+ }
+
+ @Test
+ void testCheckServerIdentityMatched() throws NoSuchMethodException {
+ when(authConfig.getServerIdentityKey()).thenReturn("1");
+ when(authConfig.getServerIdentityValue()).thenReturn("2");
+ when(request.getHeader("1")).thenReturn("2");
+ Secured secured = getMethodSecure("testCheckServerIdentityMatched");
+ ServerIdentityResult result = protocolAuthService.checkServerIdentity(request, secured);
+ assertEquals(ServerIdentityResult.ResultStatus.MATCHED, result.getStatus());
+ }
+
private Secured getMethodSecure(String methodName) throws NoSuchMethodException {
Method method = HttpProtocolAuthServiceTest.class.getDeclaredMethod(methodName);
return method.getAnnotation(Secured.class);
diff --git a/auth/src/test/java/com/alibaba/nacos/auth/config/AuthConfigsTest.java b/auth/src/test/java/com/alibaba/nacos/auth/config/AuthConfigsTest.java
index 1c12c3b5683..7ea2c61bbc1 100644
--- a/auth/src/test/java/com/alibaba/nacos/auth/config/AuthConfigsTest.java
+++ b/auth/src/test/java/com/alibaba/nacos/auth/config/AuthConfigsTest.java
@@ -22,8 +22,6 @@
import org.junit.jupiter.api.Test;
import org.springframework.mock.env.MockEnvironment;
-import java.util.Optional;
-
import static org.junit.jupiter.api.Assertions.assertEquals;
class AuthConfigsTest {
@@ -36,8 +34,6 @@ class AuthConfigsTest {
private static final String TEST_SERVER_IDENTITY_VALUE = "testValue";
- private static final boolean TEST_ENABLE_UA_WHITE = true;
-
private AuthConfigs authConfigs;
private MockEnvironment environment;
@@ -56,16 +52,11 @@ void testUpgradeFromEvent() {
environment.setProperty("nacos.core.auth.caching.enabled", String.valueOf(TEST_CACHING_ENABLED));
environment.setProperty("nacos.core.auth.server.identity.key", TEST_SERVER_IDENTITY_KEY);
environment.setProperty("nacos.core.auth.server.identity.value", TEST_SERVER_IDENTITY_VALUE);
- environment.setProperty("nacos.core.auth.enable.userAgentAuthWhite", String.valueOf(TEST_ENABLE_UA_WHITE));
authConfigs.onEvent(ServerConfigChangeEvent.newEvent());
- assertEquals(Optional.of(TEST_AUTH_ENABLED).orElse(Boolean.FALSE),
- Optional.of(authConfigs.isAuthEnabled()).orElse(Boolean.FALSE));
- assertEquals(Optional.of(TEST_CACHING_ENABLED).orElse(Boolean.FALSE),
- Optional.of(authConfigs.isCachingEnabled()).orElse(Boolean.FALSE));
+ assertEquals(TEST_AUTH_ENABLED, authConfigs.isAuthEnabled());
+ assertEquals(TEST_CACHING_ENABLED, authConfigs.isCachingEnabled());
assertEquals(TEST_SERVER_IDENTITY_KEY, authConfigs.getServerIdentityKey());
assertEquals(TEST_SERVER_IDENTITY_VALUE, authConfigs.getServerIdentityValue());
- assertEquals(Optional.of(TEST_ENABLE_UA_WHITE).orElse(Boolean.FALSE),
- Optional.of(authConfigs.isEnableUserAgentAuthWhite()).orElse(Boolean.FALSE));
}
}
diff --git a/auth/src/test/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilderTest.java b/auth/src/test/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilderTest.java
index 74001e1cb71..ac5a5d93f75 100644
--- a/auth/src/test/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilderTest.java
+++ b/auth/src/test/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilderTest.java
@@ -17,7 +17,7 @@
package com.alibaba.nacos.auth.context;
import com.alibaba.nacos.api.remote.request.Request;
-import com.alibaba.nacos.auth.config.AuthConfigs;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.constant.Constants;
import org.junit.jupiter.api.BeforeEach;
@@ -47,7 +47,7 @@ class GrpcIdentityContextBuilderTest {
private static final String IDENTITY_TEST_VALUE = "identity-test-value";
@Mock
- private AuthConfigs authConfigs;
+ private NacosAuthConfig authConfig;
@Mock
private Request request;
@@ -56,8 +56,8 @@ class GrpcIdentityContextBuilderTest {
@BeforeEach
void setUp() throws Exception {
- identityContextBuilder = new GrpcIdentityContextBuilder(authConfigs);
- when(authConfigs.getNacosAuthSystemType()).thenReturn(TEST_PLUGIN);
+ identityContextBuilder = new GrpcIdentityContextBuilder(authConfig);
+ when(authConfig.getNacosAuthSystemType()).thenReturn(TEST_PLUGIN);
Map headers = new HashMap<>();
headers.put(IDENTITY_TEST_KEY, IDENTITY_TEST_VALUE);
when(request.getHeaders()).thenReturn(headers);
@@ -66,7 +66,7 @@ void setUp() throws Exception {
@Test
void testBuildWithoutPlugin() {
- when(authConfigs.getNacosAuthSystemType()).thenReturn("non-exist");
+ when(authConfig.getNacosAuthSystemType()).thenReturn("non-exist");
IdentityContext actual = identityContextBuilder.build(request);
assertNull(actual.getParameter(IDENTITY_TEST_KEY));
}
diff --git a/auth/src/test/java/com/alibaba/nacos/auth/context/HtppIdentityContextBuilderTest.java b/auth/src/test/java/com/alibaba/nacos/auth/context/HtppIdentityContextBuilderTest.java
index 06abf9d4420..602722f66f8 100644
--- a/auth/src/test/java/com/alibaba/nacos/auth/context/HtppIdentityContextBuilderTest.java
+++ b/auth/src/test/java/com/alibaba/nacos/auth/context/HtppIdentityContextBuilderTest.java
@@ -16,7 +16,7 @@
package com.alibaba.nacos.auth.context;
-import com.alibaba.nacos.auth.config.AuthConfigs;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.constant.Constants;
import org.junit.jupiter.api.BeforeEach;
@@ -46,7 +46,7 @@ class HtppIdentityContextBuilderTest {
private static final String IDENTITY_TEST_VALUE = "identity-test-value";
@Mock
- private AuthConfigs authConfigs;
+ private NacosAuthConfig authConfig;
@Mock
private HttpServletRequest request;
@@ -61,15 +61,15 @@ class HtppIdentityContextBuilderTest {
@BeforeEach
void setUp() throws Exception {
- identityContextBuilder = new HttpIdentityContextBuilder(authConfigs);
- when(authConfigs.getNacosAuthSystemType()).thenReturn(TEST_PLUGIN);
+ identityContextBuilder = new HttpIdentityContextBuilder(authConfig);
+ when(authConfig.getNacosAuthSystemType()).thenReturn(TEST_PLUGIN);
}
@Test
void testBuildWithoutPlugin() {
mockHeader(true);
mockParameter(true);
- when(authConfigs.getNacosAuthSystemType()).thenReturn("non-exist");
+ when(authConfig.getNacosAuthSystemType()).thenReturn("non-exist");
IdentityContext actual = identityContextBuilder.build(request);
assertNull(actual.getParameter(IDENTITY_TEST_KEY));
}
diff --git a/auth/src/test/java/com/alibaba/nacos/auth/parser/http/ConfigHttpResourceParserTest.java b/auth/src/test/java/com/alibaba/nacos/auth/parser/http/ConfigHttpResourceParserTest.java
index 6f8c697697c..6043ba7534b 100644
--- a/auth/src/test/java/com/alibaba/nacos/auth/parser/http/ConfigHttpResourceParserTest.java
+++ b/auth/src/test/java/com/alibaba/nacos/auth/parser/http/ConfigHttpResourceParserTest.java
@@ -100,7 +100,7 @@ void testParseWithoutNamespace() throws NoSuchMethodException {
Mockito.when(request.getParameter(eq(Constants.GROUP))).thenReturn("testG");
Mockito.when(request.getParameter(eq(Constants.DATA_ID))).thenReturn("testD");
Resource actual = resourceParser.parse(request, secured);
- assertEquals(StringUtils.EMPTY, actual.getNamespaceId());
+ assertEquals(Constants.DEFAULT_NAMESPACE_ID, actual.getNamespaceId());
assertEquals("testG", actual.getGroup());
assertEquals("testD", actual.getName());
assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());
diff --git a/auth/src/test/java/com/alibaba/nacos/auth/parser/http/NamingHttpResourceParserTest.java b/auth/src/test/java/com/alibaba/nacos/auth/parser/http/NamingHttpResourceParserTest.java
index 89adf0ddc87..86b3398bed8 100644
--- a/auth/src/test/java/com/alibaba/nacos/auth/parser/http/NamingHttpResourceParserTest.java
+++ b/auth/src/test/java/com/alibaba/nacos/auth/parser/http/NamingHttpResourceParserTest.java
@@ -73,7 +73,7 @@ void testParseWithoutNamespace() throws NoSuchMethodException {
Mockito.when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn("testG");
Mockito.when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn("testS");
Resource actual = resourceParser.parse(request, secured);
- assertEquals(StringUtils.EMPTY, actual.getNamespaceId());
+ assertEquals(Constants.DEFAULT_NAMESPACE_ID, actual.getNamespaceId());
assertEquals("testG", actual.getGroup());
assertEquals("testS", actual.getName());
assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());
diff --git a/auth/src/test/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityCheckerHolderTest.java b/auth/src/test/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityCheckerHolderTest.java
new file mode 100644
index 00000000000..6b5646c21bd
--- /dev/null
+++ b/auth/src/test/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityCheckerHolderTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 1999-2023 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.auth.serveridentity;
+
+import com.alibaba.nacos.auth.annotation.Secured;
+import com.alibaba.nacos.auth.config.NacosAuthConfig;
+import com.alibaba.nacos.common.spi.NacosServiceLoader;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+
+class ServerIdentityCheckerHolderTest {
+
+ Map, Collection>> servicesMap;
+
+ @BeforeEach
+ void setUp() {
+ servicesMap = (Map, Collection>>) ReflectionTestUtils.getField(NacosServiceLoader.class,
+ "SERVICES");
+ }
+
+ @AfterEach
+ void tearDown() {
+ servicesMap.remove(ServerIdentityChecker.class);
+ }
+
+ @Test
+ void testConstructorWithSingleImplementation()
+ throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
+ ServerIdentityCheckerHolder holder = getNewHolder(1);
+ assertInstanceOf(MockChecker.class, holder.getChecker());
+ }
+
+ @Test
+ void testConstructorWithMultipleImplementation()
+ throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
+ ServerIdentityCheckerHolder holder = getNewHolder(2);
+ assertInstanceOf(MockChecker.class, holder.getChecker());
+ }
+
+ ServerIdentityCheckerHolder getNewHolder(int size)
+ throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
+ List> classes = new LinkedList<>();
+ for (int i = 0; i < size; i++) {
+ classes.add(MockChecker.class);
+ }
+ servicesMap.put(ServerIdentityChecker.class, classes);
+ Constructor constructor = ServerIdentityCheckerHolder.class.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ return constructor.newInstance();
+ }
+
+ public static class MockChecker implements ServerIdentityChecker {
+
+ @Override
+ public void init(NacosAuthConfig authConfig) {
+ }
+
+ @Override
+ public ServerIdentityResult check(ServerIdentity serverIdentity, Secured secured) {
+ return ServerIdentityResult.success();
+ }
+ }
+}
\ No newline at end of file
diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml
new file mode 100644
index 00000000000..691812b08d9
--- /dev/null
+++ b/bootstrap/pom.xml
@@ -0,0 +1,79 @@
+
+
+
+
+ 4.0.0
+
+ com.alibaba.nacos
+ nacos-all
+ ${revision}
+ ../pom.xml
+
+
+ nacos-bootstrap
+ nacos-bootstrap ${project.version}
+
+
+
+ com.alibaba.nacos
+ nacos-console
+
+
+ com.alibaba.nacos
+ nacos-server
+
+
+
+
+
+ release-nacos
+
+ nacos-server
+
+
+ maven-jar-plugin
+
+
+
+ true
+ true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ com.alibaba.nacos.bootstrap.NacosBootstrap
+ ZIP
+
+
+
+
+ repackage
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bootstrap/src/main/java/com/alibaba/nacos/bootstrap/NacosBootstrap.java b/bootstrap/src/main/java/com/alibaba/nacos/bootstrap/NacosBootstrap.java
new file mode 100644
index 00000000000..994690e6e28
--- /dev/null
+++ b/bootstrap/src/main/java/com/alibaba/nacos/bootstrap/NacosBootstrap.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 1999-2023 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.bootstrap;
+
+import com.alibaba.nacos.NacosServerBasicApplication;
+import com.alibaba.nacos.NacosServerWebApplication;
+import com.alibaba.nacos.console.NacosConsole;
+import com.alibaba.nacos.core.listener.startup.NacosStartUp;
+import com.alibaba.nacos.core.listener.startup.NacosStartUpManager;
+import com.alibaba.nacos.sys.env.Constants;
+import org.springframework.boot.Banner;
+import org.springframework.boot.ResourceBanner;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.jmx.export.MBeanExporter;
+import org.springframework.jmx.support.RegistrationPolicy;
+
+/**
+ * Nacos bootstrap class.
+ *
+ * @author xiweng.yy
+ */
+@SpringBootApplication
+public class NacosBootstrap {
+
+ private static final String SPRING_JXM_ENABLED = "spring.jmx.enabled";
+
+ public static void main(String[] args) {
+ ConfigurableApplicationContext coreContext = startCoreContext(args);
+ String type = prepareCoreContext(coreContext);
+ if (Constants.NACOS_DEPLOYMENT_TYPE_MERGED.equals(type)) {
+ startWithConsole(args, coreContext);
+ } else if (Constants.NACOS_DEPLOYMENT_TYPE_SERVER.equals(type)) {
+ startWithoutConsole(args, coreContext);
+ } else {
+ throw new IllegalArgumentException("Unsupported type " + type);
+ }
+ }
+
+ private static String prepareCoreContext(ConfigurableApplicationContext coreContext) {
+ if (coreContext.getEnvironment().getProperty(SPRING_JXM_ENABLED, Boolean.class, false)) {
+ // Avoid duplicate registration MBean to exporter.
+ coreContext.getBean(MBeanExporter.class).setRegistrationPolicy(RegistrationPolicy.IGNORE_EXISTING);
+ }
+ return coreContext.getEnvironment()
+ .getProperty(Constants.NACOS_DEPLOYMENT_TYPE, Constants.NACOS_DEPLOYMENT_TYPE_MERGED);
+ }
+
+ private static void startWithoutConsole(String[] args, ConfigurableApplicationContext coreContext) {
+ ConfigurableApplicationContext webContext = startServerWebContext(args, coreContext);
+ }
+
+ private static void startWithConsole(String[] args, ConfigurableApplicationContext coreContext) {
+ ConfigurableApplicationContext serverWebContext = startServerWebContext(args, coreContext);
+ ConfigurableApplicationContext consoleContext = startConsoleContext(args, coreContext);
+ }
+
+ private static ConfigurableApplicationContext startServerWebContext(String[] args,
+ ConfigurableApplicationContext coreContext) {
+ NacosStartUpManager.start(NacosStartUp.WEB_START_UP_PHASE);
+ return new SpringApplicationBuilder(NacosServerWebApplication.class).parent(coreContext)
+ .banner(getBanner("nacos-server-web-banner.txt")).run(args);
+ }
+
+ private static ConfigurableApplicationContext startConsoleContext(String[] args,
+ ConfigurableApplicationContext coreContext) {
+ NacosStartUpManager.start(NacosStartUp.CONSOLE_START_UP_PHASE);
+ return new SpringApplicationBuilder(NacosConsole.class).parent(coreContext)
+ .banner(getBanner("nacos-console-banner.txt")).run(args);
+ }
+
+ private static ConfigurableApplicationContext startCoreContext(String[] args) {
+ NacosStartUpManager.start(NacosStartUp.CORE_START_UP_PHASE);
+ return new SpringApplicationBuilder(NacosServerBasicApplication.class).web(WebApplicationType.NONE)
+ .banner(getBanner("core-banner.txt")).run(args);
+ }
+
+ private static Banner getBanner(String bannerFileName) {
+ return new ResourceBanner(new ClassPathResource(bannerFileName));
+ }
+}
\ No newline at end of file
diff --git a/distribution/conf/application.properties.example b/bootstrap/src/main/resources/application.properties
similarity index 59%
rename from distribution/conf/application.properties.example
rename to bootstrap/src/main/resources/application.properties
index 453630e9c57..e45a7a015d9 100644
--- a/distribution/conf/application.properties.example
+++ b/bootstrap/src/main/resources/application.properties
@@ -1,5 +1,5 @@
#
-# Copyright 1999-2021 Alibaba Group Holding Ltd.
+# Copyright 1999-2025 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.
@@ -14,13 +14,11 @@
# limitations under the License.
#
-#*************** Spring Boot Related Configurations ***************#
-### Default web context path:
-server.servlet.contextPath=/nacos
-### Include message field
-server.error.include-message=ALWAYS
-### Default web server port:
-server.port=8848
+#--------------- Nacos Common Configurations ---------------#
+
+#*************** Nacos port Related Configurations ***************#
+### Nacos Server Main port
+nacos.server.main.port=8848
#*************** Network Related Configurations ***************#
### If prefer hostname over ip for Nacos server addresses in cluster.conf:
@@ -29,85 +27,20 @@ server.port=8848
### Specify local server's IP:
# nacos.inetutils.ip-address=
-
-#*************** Config Module Related Configurations ***************#
-### If use MySQL as datasource:
-### Deprecated configuration property, it is recommended to use `spring.sql.init.platform` replaced.
-# spring.datasource.platform=mysql
-# spring.sql.init.platform=mysql
-
+#*************** Datasource Related Configurations ***************#
+### nacos.plugin.datasource.log.enabled=true
+#spring.sql.init.platform=mysql
### Count of DB:
# db.num=1
### Connect URL of DB:
# db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
-# db.user.0=nacos
-# db.password.0=nacos
-
-### Connection pool configuration: hikariCP
-db.pool.config.connectionTimeout=30000
-db.pool.config.validationTimeout=10000
-db.pool.config.maximumPoolSize=20
-db.pool.config.minimumIdle=2
-
-### the maximum retry times for push
-nacos.config.push.maxRetryTime=50
-
-#*************** Naming Module Related Configurations ***************#
-### If enable data warmup. If set to false, the server would accept request without local data preparation:
-# nacos.naming.data.warmup=true
-
-### If enable the instance auto expiration, kind like of health check of instance:
-# nacos.naming.expireInstance=true
-
-### will be removed and replaced by `nacos.naming.clean` properties
-nacos.naming.empty-service.auto-clean=true
-nacos.naming.empty-service.clean.initial-delay-ms=50000
-nacos.naming.empty-service.clean.period-time-ms=30000
-
-### Add in 2.0.0
-### The interval to clean empty service, unit: milliseconds.
-# nacos.naming.clean.empty-service.interval=60000
-
-### The expired time to clean empty service, unit: milliseconds.
-# nacos.naming.clean.empty-service.expired-time=60000
-
-### The interval to clean expired metadata, unit: milliseconds.
-# nacos.naming.clean.expired-metadata.interval=5000
-
-### The expired time to clean metadata, unit: milliseconds.
-# nacos.naming.clean.expired-metadata.expired-time=60000
-
-### The delay time before push task to execute from service changed, unit: milliseconds.
-# nacos.naming.push.pushTaskDelay=500
-
-### The timeout for push task execute, unit: milliseconds.
-# nacos.naming.push.pushTaskTimeout=5000
-
-### The delay time for retrying failed push task, unit: milliseconds.
-# nacos.naming.push.pushTaskRetryDelay=1000
-
-### Since 2.0.3
-### The expired time for inactive client, unit: milliseconds.
-# nacos.naming.client.expired.time=180000
-
-#*************** CMDB Module Related Configurations ***************#
-### The interval to dump external CMDB in seconds:
-# nacos.cmdb.dumpTaskInterval=3600
-
-### The interval of polling data change event in seconds:
-# nacos.cmdb.eventTaskInterval=10
-
-### The interval of loading labels in seconds:
-# nacos.cmdb.labelTaskInterval=300
-
-### If turn on data loading task:
-# nacos.cmdb.loadDataAtStart=false
-
+# db.user=nacos
+# db.password=nacos
#*************** Metrics Related Configurations ***************#
### Metrics for prometheus
-#management.endpoints.web.exposure.include=*
+#management.endpoints.web.exposure.include=prometheus
### Metrics for elastic search
management.metrics.export.elastic.enabled=false
@@ -121,63 +54,6 @@ management.metrics.export.influx.enabled=false
#management.metrics.export.influx.consistency=one
#management.metrics.export.influx.compressed=true
-#*************** Access Log Related Configurations ***************#
-### If turn on the access log:
-server.tomcat.accesslog.enabled=true
-
-### The access log pattern:
-server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
-
-### The directory of access log:
-server.tomcat.basedir=file:.
-
-#*************** Access Control Related Configurations ***************#
-### If enable spring security, this option is deprecated in 1.2.0:
-#spring.security.enabled=false
-
-### The ignore urls of auth, is deprecated in 1.2.0:
-nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
-
-### The auth system to use, currently only 'nacos' and 'ldap' is supported:
-nacos.core.auth.system.type=nacos
-
-### If turn on auth system:
-nacos.core.auth.enabled=false
-
-### worked when nacos.core.auth.system.type=ldap,{0} is Placeholder,replace login username
-#nacos.core.auth.system.type=ldap
-#nacos.core.auth.ldap.url=ldap://localhost:389
-#nacos.core.auth.ldap.basedc=dc=example,dc=org
-#nacos.core.auth.ldap.userDn=cn=admin,${nacos.core.auth.ldap.basedc}
-#nacos.core.auth.ldap.password=admin
-#nacos.core.auth.ldap.userdn=cn={0},dc=example,dc=org
-#nacos.core.auth.ldap.filter.prefix=uid
-#nacos.core.auth.ldap.case.sensitive=true
-#nacos.core.auth.ldap.ignore.partial.result.exception=false
-
-
-### worked when nacos.core.auth.system.type=nacos
-### The token expiration in seconds:
-nacos.core.auth.plugin.nacos.token.cache.enable=false
-nacos.core.auth.plugin.nacos.token.expire.seconds=18000
-### The default token (Base64 String):
-nacos.core.auth.plugin.nacos.token.secret.key=
-
-### Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay.
-nacos.core.auth.caching.enabled=true
-
-### Since 1.4.1, Turn on/off white auth for user-agent: nacos-server, only for upgrade from old version.
-nacos.core.auth.enable.userAgentAuthWhite=false
-
-### Since 1.4.1, worked when nacos.core.auth.enabled=true and nacos.core.auth.enable.userAgentAuthWhite=false.
-### The two properties is the white list for auth and used by identity the request from other server.
-#nacos.core.auth.server.identity.key=example
-#nacos.core.auth.server.identity.value=example
-
-#*************** Istio Related Configurations ***************#
-### If turn on the MCP server:
-nacos.istio.mcp.server.enabled=false
-
#*************** Core Related Configurations ***************#
### set the WorkerID manually
@@ -191,8 +67,10 @@ nacos.istio.mcp.server.enabled=false
### MemberLookup
### Addressing pattern category, If set, the priority is highest
# nacos.core.member.lookup.type=[file,address-server]
+
## Set the cluster list with a configuration file or command-line argument
# nacos.member.list=192.168.16.101:8847?raft_port=8807,192.168.16.101?raft_port=8808,192.168.16.101:8849?raft_port=8809
+
## for AddressServerMemberLookup
# Maximum number of retries to query the address server upon initialization
# nacos.core.address-server.retry=5
@@ -217,55 +95,200 @@ nacos.istio.mcp.server.enabled=false
# nacos.core.protocol.raft.data.read_index_type=ReadOnlySafe
### rpc request timeout, default 5 seconds
# nacos.core.protocol.raft.data.rpc_request_timeout_ms=5000
+### enable to support prometheus service discovery
+#nacos.prometheus.metrics.enabled=true
#*************** Distro Related Configurations ***************#
### Distro data sync delay time, when sync task delayed, task will be merged for same data key. Default 1 second.
# nacos.core.protocol.distro.data.sync.delayMs=1000
-
### Distro data sync timeout for one sync data, default 3 seconds.
# nacos.core.protocol.distro.data.sync.timeoutMs=3000
-
### Distro data sync retry delay time when sync data failed or timeout, same behavior with delayMs, default 3 seconds.
# nacos.core.protocol.distro.data.sync.retryDelayMs=3000
-
### Distro data verify interval time, verify synced data whether expired for a interval. Default 5 seconds.
# nacos.core.protocol.distro.data.verify.intervalMs=5000
-
### Distro data verify timeout for one verify, default 3 seconds.
# nacos.core.protocol.distro.data.verify.timeoutMs=3000
-
### Distro data load retry delay when load snapshot data failed, default 30 seconds.
# nacos.core.protocol.distro.data.load.retryDelayMs=30000
-
### enable to support prometheus service discovery
#nacos.prometheus.metrics.enabled=true
-### Since 2.3
#*************** Grpc Configurations ***************#
-## sdk grpc(between nacos server and client) configuration
-## Sets the maximum message size allowed to be received on the server.
+### Sets the maximum message size allowed to be received on the server.
#nacos.remote.server.grpc.sdk.max-inbound-message-size=10485760
-
-## Sets the time(milliseconds) without read activity before sending a keepalive ping. The typical default is two hours.
+### Sets the time(milliseconds) without read activity before sending a keepalive ping. The typical default is two hours.
#nacos.remote.server.grpc.sdk.keep-alive-time=7200000
-
-## Sets a time(milliseconds) waiting for read activity after sending a keepalive ping. Defaults to 20 seconds.
+### Sets a time(milliseconds) waiting for read activity after sending a keepalive ping. Defaults to 20 seconds.
#nacos.remote.server.grpc.sdk.keep-alive-timeout=20000
+### Sets a time(milliseconds) that specify the most aggressive keep-alive time clients are permitted to configure. The typical default is 5 minutes
+#nacos.remote.server.grpc.sdk.permit-keep-alive-time=300000
+### cluster grpc(inside the nacos server) configuration
+#nacos.remote.server.grpc.cluster.max-inbound-message-size=10485760
+### Sets the time(milliseconds) without read activity before sending a keepalive ping. The typical default is two hours.
+#nacos.remote.server.grpc.cluster.keep-alive-time=7200000
+### Sets a time(milliseconds) waiting for read activity after sending a keepalive ping. Defaults to 20 seconds.
+#nacos.remote.server.grpc.cluster.keep-alive-timeout=20000
+### Sets a time(milliseconds) that specify the most aggressive keep-alive time clients are permitted to configure. The typical default is 5 minutes
+#nacos.remote.server.grpc.cluster.permit-keep-alive-time=300000
+#*************** Config Module Related Configurations ***************#
-## Sets a time(milliseconds) that specify the most aggressive keep-alive time clients are permitted to configure. The typical default is 5 minutes
-#nacos.remote.server.grpc.sdk.permit-keep-alive-time=300000
+### the maximum retry times for push
+nacos.config.push.maxRetryTime=50
-## cluster grpc(inside the nacos server) configuration
-#nacos.remote.server.grpc.cluster.max-inbound-message-size=10485760
+#*************** Naming Module Related Configurations ***************#
+### Data dispatch task execution period in milliseconds:
-## Sets the time(milliseconds) without read activity before sending a keepalive ping. The typical default is two hours.
-#nacos.remote.server.grpc.cluster.keep-alive-time=7200000
+### If enable data warmup. If set to false, the server would accept request without local data preparation:
+# nacos.naming.data.warmup=true
-## Sets a time(milliseconds) waiting for read activity after sending a keepalive ping. Defaults to 20 seconds.
-#nacos.remote.server.grpc.cluster.keep-alive-timeout=20000
+### If enable the instance auto expiration, kind like of health check of instance:
+# nacos.naming.expireInstance=true
+
+nacos.naming.empty-service.auto-clean=true
+nacos.naming.empty-service.clean.initial-delay-ms=50000
+nacos.naming.empty-service.clean.period-time-ms=30000
+
+#--------------- Nacos Web Server Configurations ---------------#
+
+#*************** Nacos Web Server Related Configurations ***************#
+### Nacos Server Web context path:
+nacos.server.contextPath=/nacos
+
+#*************** Access Log Related Configurations ***************#
+### If turn on the access log:
+server.tomcat.accesslog.enabled=true
+
+### accesslog automatic cleaning time
+server.tomcat.accesslog.max-days=30
+
+### The access log pattern:
+server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
+
+### The directory of access log:
+server.tomcat.basedir=file:.
+
+#*************** API Related Configurations ***************#
+### Include message field
+server.error.include-message=ALWAYS
+
+### Enabled for open API compatibility
+# nacos.core.api.compatibility.client.enabled=true
+### Enabled for admin API compatibility
+# nacos.core.api.compatibility.admin.enabled=true
+### Enabled for console API compatibility
+# nacos.core.api.compatibility.console.enabled=false
+
+#--------------- Nacos Console Configurations ---------------#
+
+#*************** Nacos Console Related Configurations ***************#
+### Nacos Console Main port
+nacos.console.port=8080
+### Nacos Server Web context path:
+nacos.console.contextPath=
+
+#************** Console UI Configuration ***************#
+
+### Turn on/off the nacos console ui.
+#nacos.console.ui.enabled=true
+
+#--------------- Nacos Plugin Configurations ---------------#
+
+#*************** CMDB Plugin Related Configurations ***************#
+### The interval to dump external CMDB in seconds:
+# nacos.cmdb.dumpTaskInterval=3600
+
+### The interval of polling data change event in seconds:
+# nacos.cmdb.eventTaskInterval=10
+
+### The interval of loading labels in seconds:
+# nacos.cmdb.labelTaskInterval=300
+
+### If turn on data loading task:
+# nacos.cmdb.loadDataAtStart=false
+
+#*************** Auth Plugin Related Configurations ***************#
+### The ignore urls of auth, will be deprecated in the future:
+nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
+
+### The auth system to use, default 'nacos' and 'ldap' is supported, other type should be implemented by yourself:
+nacos.core.auth.system.type=nacos
+
+### If turn on auth system:
+# Whether open nacos server API auth system
+nacos.core.auth.enabled=false
+# Whether open nacos console API auth system
+nacos.core.auth.console.enabled=true
+
+### Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay.
+nacos.core.auth.caching.enabled=true
+
+### worked when nacos.core.auth.enabled=true
+### The two properties is the white list for auth and used by identity the request from other server.
+nacos.core.auth.server.identity.key=
+nacos.core.auth.server.identity.value=
+
+### worked when nacos.core.auth.system.type=nacos or nacos.core.auth.console.enabled=true
+### The token expiration in seconds:
+nacos.core.auth.plugin.nacos.token.cache.enable=false
+nacos.core.auth.plugin.nacos.token.expire.seconds=18000
+### The default token (Base64 string):
+#nacos.core.auth.plugin.nacos.token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=
+nacos.core.auth.plugin.nacos.token.secret.key=
+
+### worked when nacos.core.auth.system.type=ldap,{0} is Placeholder,replace login username
+#nacos.core.auth.ldap.url=ldap://localhost:389
+#nacos.core.auth.ldap.basedc=dc=example,dc=org
+#nacos.core.auth.ldap.userDn=cn=admin,${nacos.core.auth.ldap.basedc}
+#nacos.core.auth.ldap.password=admin
+#nacos.core.auth.ldap.userdn=cn={0},dc=example,dc=org
+#nacos.core.auth.ldap.filter.prefix=uid
+#nacos.core.auth.ldap.case.sensitive=true
+#nacos.core.auth.ldap.ignore.partial.result.exception=false
+
+#*************** Control Plugin Related Configurations ***************#
+# plugin type
+#nacos.plugin.control.manager.type=nacos
+
+# local control rule storage dir, default ${nacos.home}/data/connection and ${nacos.home}/data/tps
+#nacos.plugin.control.rule.local.basedir=${nacos.home}
+
+# external control rule storage type, if exist
+#nacos.plugin.control.rule.external.storage=
+
+#*************** Config Change Plugin Related Configurations ***************#
+# webhook
+#nacos.core.config.plugin.webhook.enabled=false
+# It is recommended to use EB https://help.aliyun.com/document_detail/413974.html
+#nacos.core.config.plugin.webhook.url=http://localhost:8080/webhook/send?token=***
+# The content push max capacity ,byte
+#nacos.core.config.plugin.webhook.contentMaxCapacity=102400
+
+# whitelist
+#nacos.core.config.plugin.whitelist.enabled=false
+# The import file suffixs
+#nacos.core.config.plugin.whitelist.suffixs=xml,text,properties,yaml,html
+# fileformatcheck,which validate the import file of type and content
+#nacos.core.config.plugin.fileformatcheck.enabled=false
+
+#*************** Istio Plugin Related Configurations ***************#
+### If turn on the MCP server:
+nacos.istio.mcp.server.enabled=false
+
+#--------------- Nacos Experimental Features Configurations ---------------#
+
+#*************** K8s Related Configurations ***************#
+### If turn on the K8s sync:
+nacos.k8s.sync.enabled=false
+
+### If use the Java API from an application outside a kubernetes cluster
+#nacos.k8s.sync.outsideCluster=false
+#nacos.k8s.sync.kubeConfig=/.kube/config
+
+#*************** Deployment Type Configuration ***************#
-## Sets a time(milliseconds) that specify the most aggressive keep-alive time clients are permitted to configure. The typical default is 5 minutes
-#nacos.remote.server.grpc.cluster.permit-keep-alive-time=300000
\ No newline at end of file
+### Sets the deployment type: 'merged' for joint deployment, 'server' for separate deployment server only, 'console' for separate deployment console only.
+nacos.deployment.type=merged
diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/impl/NacosAuthLoginConstant.java b/client/src/main/java/com/alibaba/nacos/client/auth/impl/NacosAuthLoginConstant.java
index df1d6369cba..aa38a97e70a 100644
--- a/client/src/main/java/com/alibaba/nacos/client/auth/impl/NacosAuthLoginConstant.java
+++ b/client/src/main/java/com/alibaba/nacos/client/auth/impl/NacosAuthLoginConstant.java
@@ -37,5 +37,5 @@ public class NacosAuthLoginConstant {
public static final String SERVER = "server";
-
+ public static final String RELOGINFLAG = "reLoginFlag";
}
diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImpl.java b/client/src/main/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImpl.java
index c374c1a9b77..eb3b41a2583 100644
--- a/client/src/main/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImpl.java
+++ b/client/src/main/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImpl.java
@@ -59,6 +59,10 @@ public class NacosClientAuthServiceImpl extends AbstractClientAuthService {
*/
private volatile LoginIdentityContext loginIdentityContext = new LoginIdentityContext();
+ /**
+ * Re-login window in milliseconds.
+ */
+ private final long reLoginWindow = 60000;
/**
* Login to servers.
@@ -69,9 +73,16 @@ public class NacosClientAuthServiceImpl extends AbstractClientAuthService {
@Override
public Boolean login(Properties properties) {
try {
- if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS
- .toMillis(tokenTtl - tokenRefreshWindow)) {
- return true;
+ boolean reLoginFlag = Boolean.parseBoolean(loginIdentityContext.getParameter(NacosAuthLoginConstant.RELOGINFLAG, "false"));
+ if (reLoginFlag) {
+ if ((System.currentTimeMillis() - lastRefreshTime) < reLoginWindow) {
+ return true;
+ }
+ } else {
+ if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS
+ .toMillis(tokenTtl - tokenRefreshWindow)) {
+ return true;
+ }
}
if (StringUtils.isBlank(properties.getProperty(PropertyKeyConst.USERNAME))) {
diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/ram/RamClientAuthServiceImpl.java b/client/src/main/java/com/alibaba/nacos/client/auth/ram/RamClientAuthServiceImpl.java
index e66565d084a..fcb523ed73f 100644
--- a/client/src/main/java/com/alibaba/nacos/client/auth/ram/RamClientAuthServiceImpl.java
+++ b/client/src/main/java/com/alibaba/nacos/client/auth/ram/RamClientAuthServiceImpl.java
@@ -21,6 +21,7 @@
import com.alibaba.nacos.client.auth.ram.identify.StsConfig;
import com.alibaba.nacos.client.auth.ram.injector.AbstractResourceInjector;
import com.alibaba.nacos.client.auth.ram.injector.ConfigResourceInjector;
+import com.alibaba.nacos.client.auth.ram.injector.LockResourceInjector;
import com.alibaba.nacos.client.auth.ram.injector.NamingResourceInjector;
import com.alibaba.nacos.client.auth.ram.utils.RamUtil;
import com.alibaba.nacos.client.auth.ram.utils.SpasAdapter;
@@ -54,6 +55,7 @@ public RamClientAuthServiceImpl() {
resourceInjectors = new HashMap<>();
resourceInjectors.put(SignType.NAMING, new NamingResourceInjector());
resourceInjectors.put(SignType.CONFIG, new ConfigResourceInjector());
+ resourceInjectors.put(SignType.LOCK, new LockResourceInjector());
}
@Override
diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/LockResourceInjector.java b/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/LockResourceInjector.java
new file mode 100644
index 00000000000..82745d7ac58
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/LockResourceInjector.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 1999-2023 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.client.auth.ram.injector;
+
+import com.alibaba.nacos.client.auth.ram.RamContext;
+import com.alibaba.nacos.client.auth.ram.identify.IdentifyConstants;
+import com.alibaba.nacos.client.auth.ram.identify.StsConfig;
+import com.alibaba.nacos.client.auth.ram.identify.StsCredential;
+import com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder;
+import com.alibaba.nacos.common.utils.StringUtils;
+import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;
+import com.alibaba.nacos.plugin.auth.api.RequestResource;
+
+/**
+ * lock resource injector.
+ *
+ * @author 985492783@qq.com
+ * @date 2023/9/17 1:10
+ */
+public class LockResourceInjector extends AbstractResourceInjector {
+
+ private static final String AK_FIELD = "ak";
+
+ @Override
+ public void doInject(RequestResource resource, RamContext context, LoginIdentityContext result) {
+ String accessKey = context.getAccessKey();
+ String secretKey = context.getSecretKey();
+ // STS 临时凭证鉴权的优先级高于 AK/SK 鉴权
+ if (StsConfig.getInstance().isStsOn()) {
+ StsCredential stsCredential = StsCredentialHolder.getInstance().getStsCredential();
+ accessKey = stsCredential.getAccessKeyId();
+ secretKey = stsCredential.getAccessKeySecret();
+ result.setParameter(IdentifyConstants.SECURITY_TOKEN_HEADER, stsCredential.getSecurityToken());
+ }
+
+ if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotBlank(secretKey)) {
+ result.setParameter(AK_FIELD, accessKey);
+ }
+ }
+}
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 bf5099e6009..a8629ecb0dc 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
@@ -1221,10 +1221,17 @@ private Response requestProxy(RpcClient rpcClientInner, Request request, long ti
throw new NacosException(NacosException.CLIENT_OVER_THRESHOLD,
"More than client-side current limit threshold");
}
+ Response response;
if (timeoutMills < 0) {
- return rpcClientInner.request(request);
+ response = rpcClientInner.request(request);
+ } else {
+ response = rpcClientInner.request(request, timeoutMills);
+ }
+ // If the 403 login operation is triggered, refresh the accessToken of the client
+ if (response.getErrorCode() == ConfigQueryResponse.NO_RIGHT) {
+ reLogin();
}
- return rpcClientInner.request(request, timeoutMills);
+ return response;
}
private RequestResource resourceBuild(Request request) {
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigHttpClientManager.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigHttpClientManager.java
index 86de1116312..93b4287fe59 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigHttpClientManager.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigHttpClientManager.java
@@ -71,14 +71,14 @@ public static ConfigHttpClientManager getInstance() {
@Override
public void shutdown() throws NacosException {
- NAMING_LOGGER.warn("[ConfigHttpClientManager] Start destroying NacosRestTemplate");
+ NAMING_LOGGER.info("[ConfigHttpClientManager] Start destroying NacosRestTemplate");
try {
HttpClientBeanHolder.shutdownNacosSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
} catch (Exception ex) {
NAMING_LOGGER.error("[ConfigHttpClientManager] An exception occurred when the HTTP client was closed : {}",
ExceptionUtil.getStackTrace(ex));
}
- NAMING_LOGGER.warn("[ConfigHttpClientManager] Destruction of the end");
+ NAMING_LOGGER.info("[ConfigHttpClientManager] Completed destruction of NacosRestTemplate");
}
/**
diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java
index 60d321f1620..1bd5a8e10c5 100644
--- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java
+++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java
@@ -79,7 +79,7 @@ public ConfigTransportClient(NacosClientProperties properties, ConfigServerListM
this.tenant = properties.getProperty(PropertyKeyConst.NAMESPACE);
this.serverListManager = serverListManager;
this.properties = properties.asProperties();
- this.securityProxy = new SecurityProxy(serverListManager.getServerList(),
+ this.securityProxy = new SecurityProxy(serverListManager,
ConfigHttpClientManager.getInstance().getNacosRestTemplate());
}
@@ -136,6 +136,10 @@ public void start() throws NacosException {
startInternal();
}
+ public void reLogin() {
+ securityProxy.reLogin();
+ }
+
/**
* start client inner.
*
diff --git a/client/src/main/java/com/alibaba/nacos/client/lock/NacosLockService.java b/client/src/main/java/com/alibaba/nacos/client/lock/NacosLockService.java
new file mode 100644
index 00000000000..fcaf42f3073
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/lock/NacosLockService.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 1999-2023 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.client.lock;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.lock.LockService;
+import com.alibaba.nacos.api.lock.model.LockInstance;
+import com.alibaba.nacos.client.address.AbstractServerListManager;
+import com.alibaba.nacos.client.env.NacosClientProperties;
+import com.alibaba.nacos.client.lock.remote.grpc.LockGrpcClient;
+import com.alibaba.nacos.client.naming.core.NamingServerListManager;
+import com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager;
+import com.alibaba.nacos.client.security.SecurityProxy;
+
+import java.util.Properties;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import static com.alibaba.nacos.client.constant.Constants.Security.SECURITY_INFO_REFRESH_INTERVAL_MILLS;
+
+/**
+ * nacos lock Service.
+ *
+ * @author 985492783@qq.com
+ * @date 2023/8/24 19:51
+ */
+@SuppressWarnings("PMD.ServiceOrDaoClassShouldEndWithImplRule")
+public class NacosLockService implements LockService {
+
+ private final Properties properties;
+
+ private final LockGrpcClient lockGrpcClient;
+
+ private final SecurityProxy securityProxy;
+
+ private ScheduledExecutorService executorService;
+
+ public NacosLockService(Properties properties) throws NacosException {
+ this.properties = properties;
+ NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);
+ AbstractServerListManager serverListManager = new NamingServerListManager(properties);
+ this.securityProxy = new SecurityProxy(serverListManager,
+ NamingHttpClientManager.getInstance().getNacosRestTemplate());
+ initSecurityProxy(nacosClientProperties);
+ this.lockGrpcClient = new LockGrpcClient(nacosClientProperties, serverListManager, securityProxy);
+ }
+
+ private void initSecurityProxy(NacosClientProperties properties) {
+ this.executorService = new ScheduledThreadPoolExecutor(1, r -> {
+ Thread t = new Thread(r);
+ t.setName("com.alibaba.nacos.client.lock.security");
+ t.setDaemon(true);
+ return t;
+ });
+ final Properties nacosClientPropertiesView = properties.asProperties();
+ this.securityProxy.login(nacosClientPropertiesView);
+ this.executorService.scheduleWithFixedDelay(() -> securityProxy.login(nacosClientPropertiesView), 0,
+ SECURITY_INFO_REFRESH_INTERVAL_MILLS, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public Boolean lock(LockInstance instance) throws NacosException {
+ return instance.lock(this);
+ }
+
+ @Override
+ public Boolean unLock(LockInstance instance) throws NacosException {
+ return instance.unLock(this);
+ }
+
+ @Override
+ public Boolean remoteTryLock(LockInstance instance) throws NacosException {
+ return lockGrpcClient.lock(instance);
+ }
+
+ @Override
+ public Boolean remoteReleaseLock(LockInstance instance) throws NacosException {
+ return lockGrpcClient.unLock(instance);
+ }
+
+ public Properties getProperties() {
+ return properties;
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/lock/core/NLock.java b/client/src/main/java/com/alibaba/nacos/client/lock/core/NLock.java
new file mode 100644
index 00000000000..3582cbb6eee
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/lock/core/NLock.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1999-2023 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.client.lock.core;
+
+import com.alibaba.nacos.api.lock.common.LockConstants;
+import com.alibaba.nacos.api.lock.model.LockInstance;
+
+/**
+ * Nacos client lock entity.
+ *
+ * @author 985492783@qq.com
+ * @date 2023/8/24 19:52
+ */
+@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
+public class NLock extends LockInstance {
+
+ private static final long serialVersionUID = -346054842454875524L;
+
+ public NLock() {
+ }
+
+ public NLock(String key, Long expireTimestamp) {
+ super(key, expireTimestamp, LockConstants.NACOS_LOCK_TYPE);
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/lock/core/NLockFactory.java b/client/src/main/java/com/alibaba/nacos/client/lock/core/NLockFactory.java
new file mode 100644
index 00000000000..188259fb351
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/lock/core/NLockFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 1999-2023 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.client.lock.core;
+
+/**
+ * NLock factory.
+ *
+ * @author 985492783@qq.com
+ * @date 2023/8/27 15:23
+ */
+@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
+public class NLockFactory {
+
+ /**
+ * create NLock without expireTime.
+ *
+ * @param key key
+ * @return NLock
+ */
+ public static NLock getLock(String key) {
+ return new NLock(key, -1L);
+ }
+
+ /**
+ * create NLock with expireTime.
+ *
+ * @param key key
+ * @return NLock
+ */
+ public static NLock getLock(String key, Long expireTimestamp) {
+ return new NLock(key, expireTimestamp);
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/lock/remote/AbstractLockClient.java b/client/src/main/java/com/alibaba/nacos/client/lock/remote/AbstractLockClient.java
new file mode 100644
index 00000000000..06b7b5a9bbe
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/lock/remote/AbstractLockClient.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 1999-2023 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.client.lock.remote;
+
+import com.alibaba.nacos.client.security.SecurityProxy;
+import com.alibaba.nacos.client.utils.AppNameUtils;
+import com.alibaba.nacos.plugin.auth.api.RequestResource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * abstract lock client.
+ * @author 985492783@qq.com
+ * @description AbstractLockClient
+ * @date 2023/6/28 17:19
+ */
+public abstract class AbstractLockClient implements LockClient {
+ private final SecurityProxy securityProxy;
+
+ private static final String APP_FILED = "app";
+
+ protected AbstractLockClient(SecurityProxy securityProxy) {
+ this.securityProxy = securityProxy;
+ }
+
+ protected Map getSecurityHeaders() {
+ RequestResource resource = RequestResource.lockBuilder().build();
+ Map result = this.securityProxy.getIdentityContext(resource);
+ result.putAll(getAppHeaders());
+ return result;
+ }
+
+ protected Map getAppHeaders() {
+ Map result = new HashMap<>(1);
+ result.put(APP_FILED, AppNameUtils.getAppName());
+ return result;
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/lock/remote/LockClient.java b/client/src/main/java/com/alibaba/nacos/client/lock/remote/LockClient.java
new file mode 100644
index 00000000000..facc6ba5ec3
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/lock/remote/LockClient.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 1999-2023 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.client.lock.remote;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.lock.model.LockInstance;
+import com.alibaba.nacos.common.lifecycle.Closeable;
+
+/**
+ * lock client interface.
+ *
+ * @author 985492783@qq.com
+ * @description LockClient
+ * @date 2023/6/28 17:19
+ */
+public interface LockClient extends Closeable {
+
+ /**
+ * lock client get lock.
+ *
+ * @param instance instance.
+ * @return Boolean.
+ * @throws NacosException nacos Exception.
+ */
+ Boolean lock(LockInstance instance) throws NacosException;
+
+ /**
+ * lock client unLock.
+ *
+ * @param instance instance.
+ * @return Boolean.
+ * @throws NacosException nacos Exception.
+ */
+ Boolean unLock(LockInstance instance) throws NacosException;
+
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/lock/remote/grpc/LockGrpcClient.java b/client/src/main/java/com/alibaba/nacos/client/lock/remote/grpc/LockGrpcClient.java
new file mode 100644
index 00000000000..e46ebbec137
--- /dev/null
+++ b/client/src/main/java/com/alibaba/nacos/client/lock/remote/grpc/LockGrpcClient.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 1999-2023 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.client.lock.remote.grpc;
+
+import com.alibaba.nacos.api.common.Constants;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.lock.constant.PropertyConstants;
+import com.alibaba.nacos.api.lock.model.LockInstance;
+import com.alibaba.nacos.api.lock.remote.AbstractLockRequest;
+import com.alibaba.nacos.api.lock.remote.LockOperationEnum;
+import com.alibaba.nacos.api.lock.remote.request.LockOperationRequest;
+import com.alibaba.nacos.api.lock.remote.response.LockOperationResponse;
+import com.alibaba.nacos.api.remote.RemoteConstants;
+import com.alibaba.nacos.api.remote.response.Response;
+import com.alibaba.nacos.api.remote.response.ResponseCode;
+import com.alibaba.nacos.client.env.NacosClientProperties;
+import com.alibaba.nacos.client.lock.remote.AbstractLockClient;
+import com.alibaba.nacos.client.security.SecurityProxy;
+import com.alibaba.nacos.client.utils.AppNameUtils;
+import com.alibaba.nacos.common.remote.ConnectionType;
+import com.alibaba.nacos.common.remote.client.RpcClient;
+import com.alibaba.nacos.common.remote.client.RpcClientFactory;
+import com.alibaba.nacos.common.remote.client.RpcClientTlsConfigFactory;
+import com.alibaba.nacos.common.remote.client.ServerListFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * lock grpc client.
+ *
+ * @author 985492783@qq.com
+ * @description LockGrpcClient
+ * @date 2023/6/28 17:35
+ */
+public class LockGrpcClient extends AbstractLockClient {
+
+ private final String uuid;
+
+ private final Long requestTimeout;
+
+ private final RpcClient rpcClient;
+
+ public LockGrpcClient(NacosClientProperties properties, ServerListFactory serverListFactory,
+ SecurityProxy securityProxy) throws NacosException {
+ super(securityProxy);
+ this.uuid = UUID.randomUUID().toString();
+ this.requestTimeout = Long.parseLong(properties.getProperty(PropertyConstants.LOCK_REQUEST_TIMEOUT, "-1"));
+ Map labels = new HashMap<>();
+ labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_SDK);
+ labels.put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_LOCK);
+ labels.put(Constants.APPNAME, AppNameUtils.getAppName());
+ this.rpcClient = RpcClientFactory.createClient(uuid, ConnectionType.GRPC, labels,
+ RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties.asProperties()));
+ start(serverListFactory);
+ }
+
+ private void start(ServerListFactory serverListFactory) throws NacosException {
+ rpcClient.serverListFactory(serverListFactory);
+ rpcClient.start();
+ }
+
+ @Override
+ public Boolean lock(LockInstance instance) throws NacosException {
+ LockOperationRequest request = new LockOperationRequest();
+ request.setLockInstance(instance);
+ request.setLockOperationEnum(LockOperationEnum.ACQUIRE);
+ LockOperationResponse acquireLockResponse = requestToServer(request, LockOperationResponse.class);
+ return (Boolean) acquireLockResponse.getResult();
+ }
+
+ @Override
+ public Boolean unLock(LockInstance instance) throws NacosException {
+ LockOperationRequest request = new LockOperationRequest();
+ request.setLockInstance(instance);
+ request.setLockOperationEnum(LockOperationEnum.RELEASE);
+ LockOperationResponse acquireLockResponse = requestToServer(request, LockOperationResponse.class);
+ return (Boolean) acquireLockResponse.getResult();
+ }
+
+ @Override
+ public void shutdown() throws NacosException {
+
+ }
+
+ private T requestToServer(AbstractLockRequest request, Class responseClass)
+ throws NacosException {
+ try {
+ request.putAllHeader(getSecurityHeaders());
+ Response response =
+ requestTimeout < 0 ? rpcClient.request(request) : rpcClient.request(request, requestTimeout);
+ if (ResponseCode.SUCCESS.getCode() != response.getResultCode()) {
+ throw new NacosException(response.getErrorCode(), response.getMessage());
+ }
+ if (responseClass.isAssignableFrom(response.getClass())) {
+ return (T) response;
+ }
+ } catch (NacosException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new NacosException(NacosException.SERVER_ERROR, "Request nacos server failed: ", e);
+ }
+ throw new NacosException(NacosException.SERVER_ERROR, "Server return invalid response");
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingMaintainService.java b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingMaintainService.java
index 85351f12d5f..136ee66c824 100644
--- a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingMaintainService.java
+++ b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingMaintainService.java
@@ -81,7 +81,7 @@ private void init(Properties properties) throws NacosException {
InitUtils.initWebRootContext(nacosClientProperties);
serverListManager = new NamingServerListManager(nacosClientProperties, namespace);
serverListManager.start();
- securityProxy = new SecurityProxy(serverListManager.getServerList(),
+ securityProxy = new SecurityProxy(serverListManager,
NamingHttpClientManager.getInstance().getNacosRestTemplate());
initSecurityProxy(properties);
serverProxy = new NamingHttpClientProxy(namespace, securityProxy, serverListManager, nacosClientProperties);
diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java
index 7bab2fa7f60..bf382f02e27 100644
--- a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java
+++ b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java
@@ -24,6 +24,8 @@
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
+import com.alibaba.nacos.api.naming.selector.NamingContext;
+import com.alibaba.nacos.api.naming.selector.NamingResult;
import com.alibaba.nacos.api.naming.selector.NamingSelector;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.api.selector.AbstractSelector;
@@ -37,6 +39,7 @@
import com.alibaba.nacos.client.naming.remote.NamingClientProxyDelegate;
import com.alibaba.nacos.client.naming.selector.NamingSelectorFactory;
import com.alibaba.nacos.client.naming.selector.NamingSelectorWrapper;
+import com.alibaba.nacos.client.naming.selector.ServiceInfoContext;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.alibaba.nacos.client.naming.utils.InitUtils;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
@@ -324,38 +327,67 @@ private List selectInstances(ServiceInfo serviceInfo, boolean healthy)
return list;
}
- private ServiceInfo getServiceInfoByFailover(String serviceName, String groupName, String clusterString) {
- return serviceInfoHolder.getFailoverServiceInfo(serviceName, groupName, clusterString);
+ private ServiceInfo getServiceInfo(String serviceName, String groupName, List clusters, boolean subscribe)
+ throws NacosException {
+ ServiceInfo serviceInfo;
+ NamingSelector clusterSelector = NamingSelectorFactory.newClusterSelector(clusters);
+ if (serviceInfoHolder.isFailoverSwitch()) {
+ serviceInfo = getServiceInfoByFailover(serviceName, groupName, clusterSelector);
+ if (serviceInfo != null && !serviceInfo.getHosts().isEmpty()) {
+ NAMING_LOGGER.debug("getServiceInfo from failover,serviceName: {} data:{}", serviceName,
+ JacksonUtils.toJson(serviceInfo.getHosts()));
+ return serviceInfo;
+ }
+ }
+ serviceInfo = getServiceInfoBySubscribe(serviceName, groupName, clusters, clusterSelector, subscribe);
+ return serviceInfo;
}
- private ServiceInfo getServiceInfoBySubscribe(String serviceName, String groupName, String clusterString,
- boolean subscribe) throws NacosException {
+ private ServiceInfo getServiceInfoByFailover(String serviceName, String groupName, NamingSelector clusterSelector) {
+ ServiceInfo result = serviceInfoHolder.getFailoverServiceInfo(serviceName, groupName, StringUtils.EMPTY);
+ return doSelectInstance(result, clusterSelector);
+ }
+
+ private ServiceInfo getServiceInfoBySubscribe(String serviceName, String groupName, List clusters,
+ NamingSelector selector, boolean subscribe) throws NacosException {
ServiceInfo serviceInfo;
if (subscribe) {
- serviceInfo = serviceInfoHolder.getServiceInfo(serviceName, groupName, clusterString);
- if (null == serviceInfo || !clientProxy.isSubscribed(serviceName, groupName, clusterString)) {
- serviceInfo = clientProxy.subscribe(serviceName, groupName, clusterString);
- }
+ serviceInfo = serviceInfoHolder.getServiceInfo(serviceName, groupName, StringUtils.EMPTY);
+ serviceInfo = tryToSubscribe(serviceName, groupName, serviceInfo);
+ serviceInfo = doSelectInstance(serviceInfo, selector);
} else {
+ String clusterString = NamingSelectorFactory.getUniqueClusterString(clusters);
serviceInfo = clientProxy.queryInstancesOfService(serviceName, groupName, clusterString, false);
}
return serviceInfo;
}
- private ServiceInfo getServiceInfo(String serviceName, String groupName, List clusters, boolean subscribe)
- throws NacosException {
- ServiceInfo serviceInfo;
- String clusterString = StringUtils.join(clusters, ",");
- if (serviceInfoHolder.isFailoverSwitch()) {
- serviceInfo = getServiceInfoByFailover(serviceName, groupName, clusterString);
- if (serviceInfo != null && serviceInfo.getHosts().size() > 0) {
- NAMING_LOGGER.debug("getServiceInfo from failover,serviceName: {} data:{}", serviceName,
- JacksonUtils.toJson(serviceInfo.getHosts()));
- return serviceInfo;
- }
+ private ServiceInfo tryToSubscribe(String serviceName, String groupName, ServiceInfo cachedServiceInfo) throws NacosException {
+ // not found in cache, service never subscribed.
+ if (null == cachedServiceInfo) {
+ return clientProxy.subscribe(serviceName, groupName, StringUtils.EMPTY);
}
-
- serviceInfo = getServiceInfoBySubscribe(serviceName, groupName, clusterString, subscribe);
+ // found in cache, and subscribed.
+ if (clientProxy.isSubscribed(serviceName, groupName, StringUtils.EMPTY)) {
+ return cachedServiceInfo;
+ }
+ // found in cached, but not subscribed, such as cached from local file when starting.
+ ServiceInfo result = cachedServiceInfo;
+ try {
+ result = clientProxy.subscribe(serviceName, groupName, StringUtils.EMPTY);
+ } catch (NacosException e) {
+ NAMING_LOGGER.warn("Subscribe from Server failed, will use local cache. fail message: ", e);
+ }
+ return result;
+ }
+
+ private ServiceInfo doSelectInstance(ServiceInfo serviceInfo, NamingSelector clusterSelector) {
+ if (null == serviceInfo) {
+ return null;
+ }
+ NamingContext context = new ServiceInfoContext(serviceInfo);
+ NamingResult result = clusterSelector.select(context);
+ serviceInfo.setHosts(result.getResult());
return serviceInfo;
}
diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/remote/AbstractNamingClientProxy.java b/client/src/main/java/com/alibaba/nacos/client/naming/remote/AbstractNamingClientProxy.java
index 7fa7a8ab9e5..9a684617a7c 100644
--- a/client/src/main/java/com/alibaba/nacos/client/naming/remote/AbstractNamingClientProxy.java
+++ b/client/src/main/java/com/alibaba/nacos/client/naming/remote/AbstractNamingClientProxy.java
@@ -54,4 +54,8 @@ protected Map getAppHeaders() {
result.put(APP_FILED, AppNameUtils.getAppName());
return result;
}
+
+ protected void reLogin() {
+ securityProxy.reLogin();
+ }
}
diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegate.java b/client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegate.java
index beef78ad036..efd7bdabf46 100644
--- a/client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegate.java
+++ b/client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegate.java
@@ -74,7 +74,7 @@ public NamingClientProxyDelegate(String namespace, ServiceInfoHolder serviceInfo
this.serverListManager = new NamingServerListManager(properties, namespace);
this.serverListManager.start();
this.serviceInfoHolder = serviceInfoHolder;
- this.securityProxy = new SecurityProxy(this.serverListManager.getServerList(),
+ this.securityProxy = new SecurityProxy(this.serverListManager,
NamingHttpClientManager.getInstance().getNacosRestTemplate());
initSecurityProxy(properties);
this.httpClientProxy = new NamingHttpClientProxy(namespace, securityProxy, serverListManager, properties);
diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxy.java b/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxy.java
index 27e44ce1ff3..508b76f0ab3 100644
--- a/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxy.java
+++ b/client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxy.java
@@ -446,6 +446,10 @@ private T requestToServer(AbstractNamingRequest request, Cl
getSecurityHeaders(request.getNamespace(), request.getGroupName(), request.getServiceName()));
response = requestTimeout < 0 ? rpcClient.request(request) : rpcClient.request(request, requestTimeout);
if (ResponseCode.SUCCESS.getCode() != response.getResultCode()) {
+ // If the 403 login operation is triggered, refresh the accessToken of the client
+ if (NacosException.NO_RIGHT == response.getErrorCode()) {
+ reLogin();
+ }
throw new NacosException(response.getErrorCode(), response.getMessage());
}
if (responseClass.isAssignableFrom(response.getClass())) {
diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientManager.java b/client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientManager.java
index 64ea659d1f9..4b6865b0c94 100644
--- a/client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientManager.java
+++ b/client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientManager.java
@@ -68,14 +68,14 @@ public NacosRestTemplate getNacosRestTemplate() {
@Override
public void shutdown() throws NacosException {
- NAMING_LOGGER.warn("[NamingHttpClientManager] Start destroying NacosRestTemplate");
+ NAMING_LOGGER.info("[NamingHttpClientManager] Start destroying NacosRestTemplate");
try {
HttpClientBeanHolder.shutdownNacosSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
} catch (Exception ex) {
NAMING_LOGGER.error("[NamingHttpClientManager] An exception occurred when the HTTP client was closed : {}",
ExceptionUtil.getStackTrace(ex));
}
- NAMING_LOGGER.warn("[NamingHttpClientManager] Destruction of the end");
+ NAMING_LOGGER.info("[NamingHttpClientManager] Completed destruction of NacosRestTemplate");
}
private static class NamingHttpClientFactory extends AbstractHttpClientFactory {
diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxy.java b/client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxy.java
index f2ed0fe768e..30ccc039b2d 100644
--- a/client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxy.java
+++ b/client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxy.java
@@ -440,6 +440,12 @@ public String callServer(String api, Map params, Map getInstances() {
+ return serviceInfo.getHosts();
+ }
+}
diff --git a/client/src/main/java/com/alibaba/nacos/client/security/SecurityProxy.java b/client/src/main/java/com/alibaba/nacos/client/security/SecurityProxy.java
index d0362719be3..5199662d6c9 100644
--- a/client/src/main/java/com/alibaba/nacos/client/security/SecurityProxy.java
+++ b/client/src/main/java/com/alibaba/nacos/client/security/SecurityProxy.java
@@ -17,15 +17,22 @@
package com.alibaba.nacos.client.security;
import com.alibaba.nacos.api.exception.NacosException;
-import com.alibaba.nacos.plugin.auth.spi.client.ClientAuthPluginManager;
-import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;
-import com.alibaba.nacos.plugin.auth.spi.client.ClientAuthService;
-import com.alibaba.nacos.plugin.auth.api.RequestResource;
+import com.alibaba.nacos.client.address.AbstractServerListManager;
+import com.alibaba.nacos.client.address.ServerListChangeEvent;
+import com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.lifecycle.Closeable;
+import com.alibaba.nacos.common.notify.Event;
+import com.alibaba.nacos.common.notify.NotifyCenter;
+import com.alibaba.nacos.common.notify.listener.Subscriber;
+import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;
+import com.alibaba.nacos.plugin.auth.api.RequestResource;
+import com.alibaba.nacos.plugin.auth.spi.client.ClientAuthPluginManager;
+import com.alibaba.nacos.plugin.auth.spi.client.ClientAuthService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -37,18 +44,30 @@
*/
public class SecurityProxy implements Closeable {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SecurityProxy.class);
+
private ClientAuthPluginManager clientAuthPluginManager;
/**
- * Construct from serverList, nacosRestTemplate, init client auth plugin.
- * // TODO change server list to serverListManager after serverListManager refactor and unite.
+ * Construct from serverListManager, nacosRestTemplate, init client auth plugin.
*
- * @param serverList a server list that client request to.
+ * @param serverListManager a server list manager that client request to.
* @Param nacosRestTemplate http request template.
*/
- public SecurityProxy(List serverList, NacosRestTemplate nacosRestTemplate) {
+ public SecurityProxy(AbstractServerListManager serverListManager, NacosRestTemplate nacosRestTemplate) {
clientAuthPluginManager = new ClientAuthPluginManager();
- clientAuthPluginManager.init(serverList, nacosRestTemplate);
+ clientAuthPluginManager.init(serverListManager.getServerList(), nacosRestTemplate);
+ NotifyCenter.registerSubscriber(new Subscriber() {
+ @Override
+ public void onEvent(ServerListChangeEvent event) {
+ clientAuthPluginManager.refreshServerList(serverListManager.getServerList());
+ }
+
+ @Override
+ public Class extends Event> subscribeType() {
+ return ServerListChangeEvent.class;
+ }
+ });
}
/**
@@ -85,4 +104,23 @@ public Map getIdentityContext(RequestResource resource) {
public void shutdown() throws NacosException {
clientAuthPluginManager.shutdown();
}
+
+ /**
+ * Login again to refresh the accessToken.
+ */
+ public void reLogin() {
+ if (clientAuthPluginManager.getAuthServiceSpiImplSet().isEmpty()) {
+ return;
+ }
+ for (ClientAuthService clientAuthService : clientAuthPluginManager.getAuthServiceSpiImplSet()) {
+ try {
+ LoginIdentityContext loginIdentityContext = clientAuthService.getLoginIdentityContext(new RequestResource());
+ if (loginIdentityContext != null) {
+ loginIdentityContext.setParameter(NacosAuthLoginConstant.RELOGINFLAG, "true");
+ }
+ } catch (Exception e) {
+ LOGGER.error("[SecurityProxy] set reLoginFlag failed.", e);
+ }
+ }
+ }
}
diff --git a/client/src/main/java/com/alibaba/nacos/client/utils/ParamUtil.java b/client/src/main/java/com/alibaba/nacos/client/utils/ParamUtil.java
index 593407911bf..4325d60adcc 100644
--- a/client/src/main/java/com/alibaba/nacos/client/utils/ParamUtil.java
+++ b/client/src/main/java/com/alibaba/nacos/client/utils/ParamUtil.java
@@ -239,7 +239,7 @@ public static String parseNamespace(NacosClientProperties properties) {
if (StringUtils.isBlank(namespaceTmp)) {
namespaceTmp = properties.getProperty(PropertyKeyConst.NAMESPACE);
}
- return StringUtils.isNotBlank(namespaceTmp) ? namespaceTmp.trim() : StringUtils.EMPTY;
+ return StringUtils.isNotBlank(namespaceTmp) ? namespaceTmp.trim() : Constants.DEFAULT_NAMESPACE_ID;
}
/**
diff --git a/client/src/test/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImplTest.java b/client/src/test/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImplTest.java
index a2312d8b984..6508350e877 100644
--- a/client/src/test/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImplTest.java
+++ b/client/src/test/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImplTest.java
@@ -235,4 +235,19 @@ void testGetAccessTokenWithInvalidTtl() throws Exception {
//when
assertFalse(nacosClientAuthService.login(properties));
}
+
+ @Test
+ void testReLogin() {
+ NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();
+ nacosClientAuthService.login(new Properties());
+ // reLogin
+ nacosClientAuthService.getLoginIdentityContext(null).setParameter(NacosAuthLoginConstant.RELOGINFLAG, "true");
+ Properties properties = new Properties();
+ properties.setProperty(PropertyKeyConst.USERNAME, "aaa");
+ properties.setProperty(PropertyKeyConst.PASSWORD, "123456");
+ List serverList = new ArrayList<>();
+ serverList.add("localhost");
+ //when
+ assertTrue(nacosClientAuthService.login(properties));
+ }
}
diff --git a/client/src/test/java/com/alibaba/nacos/client/config/NacosConfigServiceTest.java b/client/src/test/java/com/alibaba/nacos/client/config/NacosConfigServiceTest.java
index e5287eadee5..7e56dde22d4 100644
--- a/client/src/test/java/com/alibaba/nacos/client/config/NacosConfigServiceTest.java
+++ b/client/src/test/java/com/alibaba/nacos/client/config/NacosConfigServiceTest.java
@@ -80,12 +80,12 @@ void clean() {
void testGetConfigFromServer() throws NacosException {
final String dataId = "1";
final String group = "2";
- final String tenant = "";
+ final String tenant = "public";
final int timeout = 3000;
ConfigResponse response = new ConfigResponse();
response.setContent("aa");
response.setConfigType("bb");
- Mockito.when(mockWoker.getServerConfig(dataId, group, "", timeout, false)).thenReturn(response);
+ Mockito.when(mockWoker.getServerConfig(dataId, group, tenant, timeout, false)).thenReturn(response);
final String config = nacosConfigService.getConfig(dataId, group, timeout);
assertEquals("aa", config);
Mockito.verify(mockWoker, Mockito.times(1)).getServerConfig(dataId, group, tenant, timeout, false);
@@ -96,7 +96,7 @@ void testGetConfigFromServer() throws NacosException {
void testGetConfigFromFailOver() throws NacosException {
final String dataId = "1failover";
final String group = "2";
- final String tenant = "";
+ final String tenant = "public";
MockedStatic localConfigInfoProcessorMockedStatic = Mockito.mockStatic(LocalConfigInfoProcessor.class);
try {
@@ -116,7 +116,7 @@ void testGetConfigFromFailOver() throws NacosException {
void testGetConfigFromLocalCache() throws NacosException {
final String dataId = "1localcache";
final String group = "2";
- final String tenant = "";
+ final String tenant = "public";
MockedStatic localConfigInfoProcessorMockedStatic = Mockito.mockStatic(LocalConfigInfoProcessor.class);
try {
@@ -129,7 +129,7 @@ void testGetConfigFromLocalCache() throws NacosException {
.thenReturn(contentFailOver);
//form server error.
final int timeout = 3000;
- Mockito.when(mockWoker.getServerConfig(dataId, group, "", timeout, false)).thenThrow(new NacosException());
+ Mockito.when(mockWoker.getServerConfig(dataId, group, tenant, timeout, false)).thenThrow(new NacosException());
final String config = nacosConfigService.getConfig(dataId, group, timeout);
assertEquals(contentFailOver, config);
@@ -143,7 +143,7 @@ void testGetConfigFromLocalCache() throws NacosException {
void testGetConfig403() throws NacosException {
final String dataId = "1localcache403";
final String group = "2";
- final String tenant = "";
+ final String tenant = "public";
MockedStatic localConfigInfoProcessorMockedStatic = Mockito.mockStatic(LocalConfigInfoProcessor.class);
try {
@@ -153,7 +153,7 @@ void testGetConfig403() throws NacosException {
//form server error.
final int timeout = 3000;
- Mockito.when(mockWoker.getServerConfig(dataId, group, "", timeout, false))
+ Mockito.when(mockWoker.getServerConfig(dataId, group, tenant, timeout, false))
.thenThrow(new NacosException(NacosException.NO_RIGHT, "no right"));
try {
nacosConfigService.getConfig(dataId, group, timeout);
@@ -271,7 +271,7 @@ void testPublishConfig() throws NacosException {
String dataId = "1";
String group = "2";
String content = "123";
- String namespace = "";
+ String namespace = "public";
String type = ConfigType.getDefaultType().getType();
Mockito.when(mockWoker.publishConfig(dataId, group, namespace, null, null, null, content, "", null, type)).thenReturn(true);
@@ -286,7 +286,7 @@ void testPublishConfig2() throws NacosException {
String dataId = "1";
String group = "2";
String content = "123";
- String namespace = "";
+ String namespace = "public";
String type = ConfigType.PROPERTIES.getType();
Mockito.when(mockWoker.publishConfig(dataId, group, namespace, null, null, null, content, "", null, type)).thenReturn(true);
@@ -302,7 +302,7 @@ void testPublishConfigCas() throws NacosException {
String dataId = "1";
String group = "2";
String content = "123";
- String namespace = "";
+ String namespace = "public";
String casMd5 = "96147704e3cb8be8597d55d75d244a02";
String type = ConfigType.getDefaultType().getType();
@@ -319,7 +319,7 @@ void testPublishConfigCas2() throws NacosException {
String dataId = "1";
String group = "2";
String content = "123";
- String namespace = "";
+ String namespace = "public";
String casMd5 = "96147704e3cb8be8597d55d75d244a02";
String type = ConfigType.PROPERTIES.getType();
@@ -335,7 +335,7 @@ void testPublishConfigCas2() throws NacosException {
void testRemoveConfig() throws NacosException {
String dataId = "1";
String group = "2";
- String tenant = "";
+ String tenant = "public";
Mockito.when(mockWoker.removeConfig(dataId, group, tenant, null)).thenReturn(true);
diff --git a/client/src/test/java/com/alibaba/nacos/client/config/impl/ClientWorkerTest.java b/client/src/test/java/com/alibaba/nacos/client/config/impl/ClientWorkerTest.java
index 7c3cd312962..5659c2c3684 100644
--- a/client/src/test/java/com/alibaba/nacos/client/config/impl/ClientWorkerTest.java
+++ b/client/src/test/java/com/alibaba/nacos/client/config/impl/ClientWorkerTest.java
@@ -30,6 +30,7 @@
import com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;
+import com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.common.GroupKey;
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
@@ -761,4 +762,21 @@ void testAddTenantListenersWithContentEnsureCacheDataSafe()
assertFalse(cacheDataFromCache2.isDiscard());
assertFalse(cacheDataFromCache2.isConsistentWithServer());
}
+
+ @Test
+ void testResponse403() throws NacosException {
+ Properties prop = new Properties();
+ ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());
+ ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);
+
+ final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);
+ final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);
+
+ ConfigRemoveResponse response = ConfigRemoveResponse.buildFailResponse("accessToken invalid");
+ response.setErrorCode(ConfigQueryResponse.NO_RIGHT);
+ Mockito.when(rpcClient.request(any(ConfigRemoveRequest.class)))
+ .thenReturn(response);
+ boolean result = clientWorker.removeConfig("a", "b", "c", "tag");
+ assertFalse(result);
+ }
}
diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingServiceTest.java b/client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingServiceTest.java
index 7b1b0275bf0..b1c98ee7195 100644
--- a/client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingServiceTest.java
+++ b/client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingServiceTest.java
@@ -34,6 +34,7 @@
import com.alibaba.nacos.client.naming.selector.NamingSelectorWrapper;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
+import com.alibaba.nacos.common.utils.StringUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -47,9 +48,11 @@
import java.util.Collections;
import java.util.List;
import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
import static com.alibaba.nacos.client.naming.selector.NamingSelectorFactory.getUniqueClusterString;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -118,7 +121,7 @@ private void injectMocks(NacosNamingService client) throws NoSuchFieldException,
}
@Test
- void testRegisterInstance1() throws NacosException {
+ void testRegisterInstanceSingle() throws NacosException {
//given
String serviceName = "service1";
String ip = "1.1.1.1";
@@ -133,87 +136,7 @@ void testRegisterInstance1() throws NacosException {
}
@Test
- void testBatchRegisterInstance() throws NacosException {
- Instance instance = new Instance();
- String serviceName = "service1";
- String ip = "1.1.1.1";
- int port = 10000;
- instance.setServiceName(serviceName);
- instance.setEphemeral(true);
- instance.setPort(port);
- instance.setIp(ip);
- List instanceList = new ArrayList<>();
- instanceList.add(instance);
- //when
- client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
- //then
- verify(proxy, times(1)).batchRegisterService(eq(serviceName), eq(Constants.DEFAULT_GROUP),
- argThat(instances -> CollectionUtils.isEqualCollection(instanceList, instances)));
- }
-
- @Test
- void testBatchRegisterInstanceWithGroupNamePrefix() throws NacosException {
- Instance instance = new Instance();
- String serviceName = "service1";
- String ip = "1.1.1.1";
- int port = 10000;
- instance.setServiceName(Constants.DEFAULT_GROUP + "@@" + serviceName);
- instance.setEphemeral(true);
- instance.setPort(port);
- instance.setIp(ip);
- List instanceList = new ArrayList<>();
- instanceList.add(instance);
- //when
- client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
- //then
- verify(proxy, times(1)).batchRegisterService(eq(serviceName), eq(Constants.DEFAULT_GROUP),
- argThat(instances -> CollectionUtils.isEqualCollection(instanceList, instances)));
- }
-
- @Test
- void testBatchRegisterInstanceWithWrongGroupNamePrefix() throws NacosException {
- Instance instance = new Instance();
- String serviceName = "service1";
- String ip = "1.1.1.1";
- int port = 10000;
- instance.setServiceName("WrongGroup" + "@@" + serviceName);
- instance.setEphemeral(true);
- instance.setPort(port);
- instance.setIp(ip);
- List instanceList = new ArrayList<>();
- instanceList.add(instance);
- //when
- try {
- client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
- } catch (Exception e) {
- assertTrue(e instanceof NacosException);
- assertTrue(e.getMessage().contains("wrong group name prefix of instance service name"));
- }
- }
-
- @Test
- void testBatchDeRegisterInstance() throws NacosException {
- Instance instance = new Instance();
- String serviceName = "service1";
- String ip = "1.1.1.1";
- int port = 10000;
- instance.setServiceName(serviceName);
- instance.setEphemeral(true);
- instance.setPort(port);
- instance.setIp(ip);
- List instanceList = new ArrayList<>();
- instanceList.add(instance);
- //when
- try {
- client.batchDeregisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
- } catch (Exception e) {
- assertTrue(e instanceof NacosException);
- assertTrue(e.getMessage().contains("not found"));
- }
- }
-
- @Test
- void testRegisterInstance2() throws NacosException {
+ void testRegisterInstanceSingleWithGroup() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -229,7 +152,7 @@ void testRegisterInstance2() throws NacosException {
}
@Test
- void testRegisterInstance3() throws NacosException {
+ void testRegisterInstanceSingleWithCluster() throws NacosException {
//given
String serviceName = "service1";
String clusterName = "cluster1";
@@ -245,7 +168,7 @@ void testRegisterInstance3() throws NacosException {
}
@Test
- void testRegisterInstance4() throws NacosException {
+ void testRegisterInstanceSingleFull() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -262,7 +185,7 @@ void testRegisterInstance4() throws NacosException {
}
@Test
- void testRegisterInstance5() throws NacosException {
+ void testRegisterInstanceByInstanceOnlyService() throws NacosException {
//given
String serviceName = "service1";
Instance instance = new Instance();
@@ -273,7 +196,7 @@ void testRegisterInstance5() throws NacosException {
}
@Test
- void testRegisterInstance6() throws NacosException {
+ void testRegisterInstanceByInstanceFullName() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -285,7 +208,7 @@ void testRegisterInstance6() throws NacosException {
}
@Test
- void testRegisterInstance7() throws NacosException {
+ void testRegisterInstanceByInstanceWithCluster() throws NacosException {
Throwable exception = assertThrows(NacosException.class, () -> {
//given
@@ -301,7 +224,87 @@ void testRegisterInstance7() throws NacosException {
}
@Test
- void testDeregisterInstance1() throws NacosException {
+ void testBatchRegisterInstance() throws NacosException {
+ Instance instance = new Instance();
+ String serviceName = "service1";
+ String ip = "1.1.1.1";
+ int port = 10000;
+ instance.setServiceName(serviceName);
+ instance.setEphemeral(true);
+ instance.setPort(port);
+ instance.setIp(ip);
+ List instanceList = new ArrayList<>();
+ instanceList.add(instance);
+ //when
+ client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
+ //then
+ verify(proxy, times(1)).batchRegisterService(eq(serviceName), eq(Constants.DEFAULT_GROUP),
+ argThat(instances -> CollectionUtils.isEqualCollection(instanceList, instances)));
+ }
+
+ @Test
+ void testBatchRegisterInstanceWithGroupNamePrefix() throws NacosException {
+ Instance instance = new Instance();
+ String serviceName = "service1";
+ String ip = "1.1.1.1";
+ int port = 10000;
+ instance.setServiceName(Constants.DEFAULT_GROUP + "@@" + serviceName);
+ instance.setEphemeral(true);
+ instance.setPort(port);
+ instance.setIp(ip);
+ List instanceList = new ArrayList<>();
+ instanceList.add(instance);
+ //when
+ client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
+ //then
+ verify(proxy, times(1)).batchRegisterService(eq(serviceName), eq(Constants.DEFAULT_GROUP),
+ argThat(instances -> CollectionUtils.isEqualCollection(instanceList, instances)));
+ }
+
+ @Test
+ void testBatchRegisterInstanceWithWrongGroupNamePrefix() throws NacosException {
+ Instance instance = new Instance();
+ String serviceName = "service1";
+ String ip = "1.1.1.1";
+ int port = 10000;
+ instance.setServiceName("WrongGroup" + "@@" + serviceName);
+ instance.setEphemeral(true);
+ instance.setPort(port);
+ instance.setIp(ip);
+ List instanceList = new ArrayList<>();
+ instanceList.add(instance);
+ //when
+ try {
+ client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
+ } catch (Exception e) {
+ assertTrue(e instanceof NacosException);
+ assertTrue(e.getMessage().contains("wrong group name prefix of instance service name"));
+ }
+ }
+
+ @Test
+ void testBatchDeRegisterInstance() throws NacosException {
+ Instance instance = new Instance();
+ String serviceName = "service1";
+ String ip = "1.1.1.1";
+ int port = 10000;
+ instance.setServiceName(serviceName);
+ instance.setEphemeral(true);
+ instance.setPort(port);
+ instance.setIp(ip);
+ List instanceList = new ArrayList<>();
+ instanceList.add(instance);
+ //when
+ try {
+ client.batchDeregisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
+ } catch (Exception e) {
+ assertTrue(e instanceof NacosException);
+ assertTrue(e.getMessage().contains("not found"));
+ }
+ }
+
+ @Test
+ void testDeregisterInstanceSingle() throws NacosException {
//given
String serviceName = "service1";
String ip = "1.1.1.1";
@@ -316,7 +319,7 @@ void testDeregisterInstance1() throws NacosException {
}
@Test
- void testDeregisterInstance2() throws NacosException {
+ void testDeregisterInstanceSingleWithGroup() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -332,7 +335,7 @@ void testDeregisterInstance2() throws NacosException {
}
@Test
- void testDeregisterInstance3() throws NacosException {
+ void testDeregisterInstanceSingleWithCluster() throws NacosException {
//given
String serviceName = "service1";
String clusterName = "cluster1";
@@ -348,7 +351,7 @@ void testDeregisterInstance3() throws NacosException {
}
@Test
- void testDeregisterInstance4() throws NacosException {
+ void testDeregisterInstanceSingleFull() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -365,7 +368,7 @@ void testDeregisterInstance4() throws NacosException {
}
@Test
- void testDeregisterInstance5() throws NacosException {
+ void testDeregisterInstanceByInstanceOnlyService() throws NacosException {
//given
String serviceName = "service1";
Instance instance = new Instance();
@@ -376,7 +379,7 @@ void testDeregisterInstance5() throws NacosException {
}
@Test
- void testDeregisterInstance6() throws NacosException {
+ void testDeregisterInstanceByInstanceFullName() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -388,94 +391,135 @@ void testDeregisterInstance6() throws NacosException {
}
@Test
- void testGetAllInstances1() throws NacosException {
+ void testGetAllInstancesOnlyService() throws NacosException {
//given
String serviceName = "service1";
//when
- client.getAllInstances(serviceName);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(new Instance());
+ when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, "")).thenReturn(serviceInfo);
+ List result = client.getAllInstances(serviceName);
//then
- verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, "");
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testGetAllInstances2() throws NacosException {
+ void testGetAllInstancesFullName() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
//when
- client.getAllInstances(serviceName, groupName);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.setGroupName(groupName);
+ serviceInfo.addHost(new Instance());
+ when(proxy.subscribe(serviceName, groupName, "")).thenReturn(serviceInfo);
+ List result = client.getAllInstances(serviceName, groupName);
//then
- verify(proxy, times(1)).subscribe(serviceName, groupName, "");
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testGetAllInstances3() throws NacosException {
+ void testGetAllInstancesOnlyServiceNotSubscribe() throws NacosException {
//given
String serviceName = "service1";
//when
- client.getAllInstances(serviceName, false);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(new Instance());
+ when(proxy.queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "", false)).thenReturn(serviceInfo);
+ List result = client.getAllInstances(serviceName, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "", false);
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testGetAllInstances4() throws NacosException {
+ void testGetAllInstancesFullNameNotSubscribe() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
//when
- client.getAllInstances(serviceName, groupName, false);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.setGroupName(groupName);
+ serviceInfo.addHost(new Instance());
+ when(proxy.queryInstancesOfService(serviceName, groupName, "", false)).thenReturn(serviceInfo);
+ List result = client.getAllInstances(serviceName, groupName, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, groupName, "", false);
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testGetAllInstances5() throws NacosException {
+ void testGetAllInstancesWithServiceAndClusters() throws NacosException {
//given
String serviceName = "service1";
- List clusterList = Arrays.asList("cluster1", "cluster2");
//when
- client.getAllInstances(serviceName, clusterList);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance("cluster1", false));
+ serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, false));
+ List clusterList = Arrays.asList("cluster1", "cluster2");
+ when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, "")).thenReturn(serviceInfo);
+ List result = client.getAllInstances(serviceName, clusterList);
//then
- verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, "cluster1,cluster2");
+ assertEquals(1, result.size());
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testGetAllInstances6() throws NacosException {
+ void testGetAllInstancesWithFullNameAndClusters() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
+ // when
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.setGroupName(groupName);
+ serviceInfo.addHost(mockInstance("cluster1", false));
+ serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, false));
List clusterList = Arrays.asList("cluster1", "cluster2");
- //when
- client.getAllInstances(serviceName, groupName, clusterList);
+ serviceInfo.getHosts().get(1).setClusterName(Constants.DEFAULT_CLUSTER_NAME);
+ when(proxy.subscribe(serviceName, groupName, "")).thenReturn(serviceInfo);
+ List result = client.getAllInstances(serviceName, groupName, clusterList);
//then
- verify(proxy, times(1)).subscribe(serviceName, groupName, "cluster1,cluster2");
+ assertEquals(1, result.size());
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testGetAllInstances7() throws NacosException {
+ void testGetAllInstancesWithServiceAndClustersNotSubscribe() throws NacosException {
//given
String serviceName = "service1";
- List clusterList = Arrays.asList("cluster1", "cluster2");
//when
- client.getAllInstances(serviceName, clusterList, false);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance("cluster1", false));
+ List clusterList = Arrays.asList("cluster1", "cluster2");
+ when(proxy.queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "cluster1,cluster2",
+ false)).thenReturn(serviceInfo);
+ List result = client.getAllInstances(serviceName, clusterList, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "cluster1,cluster2",
- false);
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testGetAllInstances8() throws NacosException {
+ void testGetAllInstancesWithFullNameAndClustersNotSubscribe() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
+ // when
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.setGroupName(groupName);
+ serviceInfo.addHost(mockInstance("cluster1", false));
List clusterList = Arrays.asList("cluster1", "cluster2");
- //when
- client.getAllInstances(serviceName, groupName, clusterList, false);
+ when(proxy.queryInstancesOfService(serviceName, groupName, "cluster1,cluster2", false)).thenReturn(serviceInfo);
+ List result = client.getAllInstances(serviceName, groupName, clusterList, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, groupName, "cluster1,cluster2", false);
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
@@ -483,7 +527,7 @@ void testGetAllInstanceFromFailover() throws NacosException {
when(serviceInfoHolder.isFailoverSwitch()).thenReturn(true);
ServiceInfo serviceInfo = new ServiceInfo("group1@@service1");
serviceInfo.setHosts(Collections.singletonList(new Instance()));
- when(serviceInfoHolder.getFailoverServiceInfo(anyString(), anyString(), anyString())).thenReturn(serviceInfo);
+ when(serviceInfoHolder.getFailoverServiceInfo("service1", "group1", "")).thenReturn(serviceInfo);
List actual = client.getAllInstances("service1", "group1", false);
verify(proxy, never()).queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean());
assertEquals(1, actual.size());
@@ -494,101 +538,172 @@ void testGetAllInstanceFromFailover() throws NacosException {
void testGetAllInstanceFromFailoverEmpty() throws NacosException {
when(serviceInfoHolder.isFailoverSwitch()).thenReturn(true);
ServiceInfo serviceInfo = new ServiceInfo("group1@@service1");
- when(serviceInfoHolder.getFailoverServiceInfo(anyString(), anyString(), anyString())).thenReturn(serviceInfo);
+ when(serviceInfoHolder.getFailoverServiceInfo("service1", "group1", "")).thenReturn(serviceInfo);
List actual = client.getAllInstances("service1", "group1", false);
verify(proxy).queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean());
assertEquals(0, actual.size());
}
@Test
- void testSelectInstances1() throws NacosException {
+ void testGetAllInstanceWithCacheAndSubscribeException() throws NacosException {
+ String serviceName = "service1";
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(new Instance());
+ when(serviceInfoHolder.getServiceInfo(serviceName, Constants.DEFAULT_GROUP, "")).thenReturn(serviceInfo);
+ when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, "")).thenThrow(new NacosException(500, "test"));
+ List result = client.getAllInstances(serviceName);
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
+ }
+
+ @Test
+ void testGetAllInstanceWithoutCacheAndSubscribeException() throws NacosException {
+ String serviceName = "service1";
+ when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, "")).thenThrow(new NacosException(500, "test"));
+ assertThrows(NacosException.class, () -> client.getAllInstances(serviceName));
+ }
+
+ @Test
+ void testGetAllInstanceWithCacheAndSubscribed() throws NacosException {
+ String serviceName = "service1";
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(new Instance());
+ when(serviceInfoHolder.getServiceInfo(serviceName, Constants.DEFAULT_GROUP, "")).thenReturn(serviceInfo);
+ when(proxy.isSubscribed(serviceName, Constants.DEFAULT_GROUP, "")).thenReturn(true);
+ List result = client.getAllInstances(serviceName);
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
+ }
+
+ @Test
+ void testSelectInstancesOnlyService() throws NacosException {
//given
String serviceName = "service1";
//when
- client.selectInstances(serviceName, true);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
+ when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, "")).thenReturn(serviceInfo);
+ List result = client.selectInstances(serviceName, true);
//then
- verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, "");
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testSelectInstances2() throws NacosException {
+ void testSelectInstancesFullName() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
//when
- client.selectInstances(serviceName, groupName, true);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
+ when(proxy.subscribe(serviceName, groupName, "")).thenReturn(serviceInfo);
+ List result = client.selectInstances(serviceName, groupName, true);
//then
- verify(proxy, times(1)).subscribe(serviceName, groupName, "");
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testSelectInstances3() throws NacosException {
+ void testSelectInstancesOnlyServiceNotSubscribe() throws NacosException {
//given
String serviceName = "service1";
//when
- client.selectInstances(serviceName, true, false);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
+ when(proxy.queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "", false)).thenReturn(serviceInfo);
+ List result = client.selectInstances(serviceName, true, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "", false);
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testSelectInstances4() throws NacosException {
+ void testSelectInstancesFullNameNotSubscribe() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
//when
- client.selectInstances(serviceName, groupName, true, false);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
+ when(proxy.queryInstancesOfService(serviceName, groupName, "", false)).thenReturn(serviceInfo);
+ List result = client.selectInstances(serviceName, groupName, true, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, groupName, "", false);
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testSelectInstances5() throws NacosException {
+ void testSelectInstancesWithServiceAndClusters() throws NacosException {
//given
String serviceName = "service1";
- List clusterList = Arrays.asList("cluster1", "cluster2");
//when
- client.selectInstances(serviceName, clusterList, true);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance("cluster1", true));
+ serviceInfo.addHost(mockInstance("cluster1", false));
+ List clusterList = Arrays.asList("cluster1", "cluster2");
+ when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, "")).thenReturn(serviceInfo);
+ List result = client.selectInstances(serviceName, clusterList, true);
//then
- verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, "cluster1,cluster2");
+ assertEquals(1, result.size());
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testSelectInstances6() throws NacosException {
+ void testSelectInstancesWithFullNameAndClusters() throws NacosException {
//given
String serviceName = "service1";
- String groupName = "group1";
- List clusterList = Arrays.asList("cluster1", "cluster2");
+ final String groupName = "group1";
//when
- client.selectInstances(serviceName, groupName, clusterList, true);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance("cluster1", true));
+ serviceInfo.addHost(mockInstance("cluster1", false));
+ List clusterList = Arrays.asList("cluster1", "cluster2");
+ when(proxy.subscribe(serviceName, groupName, "")).thenReturn(serviceInfo);
+ List result = client.selectInstances(serviceName, groupName, clusterList, true);
//then
- verify(proxy, times(1)).subscribe(serviceName, groupName, "cluster1,cluster2");
+ assertEquals(1, result.size());
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testSelectInstances7() throws NacosException {
+ void testSelectInstancesWithServiceAndClustersNotSubscribe() throws NacosException {
//given
String serviceName = "service1";
- List clusterList = Arrays.asList("cluster1", "cluster2");
//when
- client.selectInstances(serviceName, clusterList, true, false);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance("cluster1", true));
+ serviceInfo.addHost(mockInstance("cluster1", false));
+ List clusterList = Arrays.asList("cluster1", "cluster2");
+ when(proxy.queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "cluster1,cluster2",
+ false)).thenReturn(serviceInfo);
+ List result = client.selectInstances(serviceName, clusterList, true, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "cluster1,cluster2",
- false);
+ assertEquals(1, result.size());
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
- void testSelectInstances8() throws NacosException {
+ void testSelectInstancesWithFullNameAndClustersNotSubscribe() throws NacosException {
//given
String serviceName = "service1";
- String groupName = "group1";
- List clusterList = Arrays.asList("cluster1", "cluster2");
+ final String groupName = "group1";
//when
- client.selectInstances(serviceName, groupName, clusterList, true, false);
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName(serviceName);
+ serviceInfo.addHost(mockInstance("cluster1", true));
+ serviceInfo.addHost(mockInstance("cluster1", false));
+ List clusterList = Arrays.asList("cluster1", "cluster2");
+ when(proxy.queryInstancesOfService(serviceName, groupName, "cluster1,cluster2", false)).thenReturn(serviceInfo);
+ List result = client.selectInstances(serviceName, groupName, clusterList, true, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, groupName, "cluster1,cluster2", false);
+ assertEquals(1, result.size());
+ assertEquals(serviceInfo.getHosts().get(0), result.get(0));
}
@Test
@@ -628,160 +743,123 @@ void testSelectInstancesWithHealthyFlag() throws NacosException {
}
@Test
- void testSelectOneHealthyInstance1() throws NacosException {
+ void testSelectOneHealthyInstanceOnlyService() throws NacosException {
//given
- Instance healthyInstance = new Instance();
- healthyInstance.setIp("1.1.1.1");
- healthyInstance.setPort(1000);
- List hosts = new ArrayList<>();
- hosts.add(healthyInstance);
ServiceInfo infoWithHealthyInstance = new ServiceInfo();
- infoWithHealthyInstance.setHosts(hosts);
+ infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
when(proxy.subscribe(anyString(), anyString(), anyString())).thenReturn(infoWithHealthyInstance);
String serviceName = "service1";
//when
- client.selectOneHealthyInstance(serviceName);
+ Instance instance = client.selectOneHealthyInstance(serviceName);
//then
- verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, "");
+ assertNotNull(instance);
}
@Test
- void testSelectOneHealthyInstance2() throws NacosException {
+ void testSelectOneHealthyInstanceFullName() throws NacosException {
//given
- Instance healthyInstance = new Instance();
- healthyInstance.setIp("1.1.1.1");
- healthyInstance.setPort(1000);
- List hosts = new ArrayList<>();
- hosts.add(healthyInstance);
ServiceInfo infoWithHealthyInstance = new ServiceInfo();
- infoWithHealthyInstance.setHosts(hosts);
+ infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
when(proxy.subscribe(anyString(), anyString(), anyString())).thenReturn(infoWithHealthyInstance);
String serviceName = "service1";
String groupName = "group1";
//when
- client.selectOneHealthyInstance(serviceName, groupName);
+ Instance instance = client.selectOneHealthyInstance(serviceName, groupName);
//then
- verify(proxy, times(1)).subscribe(serviceName, groupName, "");
+ assertNotNull(instance);
}
@Test
- void testSelectOneHealthyInstance3() throws NacosException {
+ void testSelectOneHealthyInstanceOnlyServiceNotSubscribe() throws NacosException {
//given
- Instance healthyInstance = new Instance();
- healthyInstance.setIp("1.1.1.1");
- healthyInstance.setPort(1000);
- List hosts = new ArrayList<>();
- hosts.add(healthyInstance);
ServiceInfo infoWithHealthyInstance = new ServiceInfo();
- infoWithHealthyInstance.setHosts(hosts);
+ infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
when(proxy.queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(
infoWithHealthyInstance);
String serviceName = "service1";
//when
- client.selectOneHealthyInstance(serviceName, false);
+ Instance instance = client.selectOneHealthyInstance(serviceName, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "", false);
+ assertNotNull(instance);
}
@Test
- void testSelectOneHealthyInstance4() throws NacosException {
+ void testSelectOneHealthyInstanceFullNameNotSubscribe() throws NacosException {
//given
- Instance healthyInstance = new Instance();
- healthyInstance.setIp("1.1.1.1");
- healthyInstance.setPort(1000);
- List hosts = new ArrayList<>();
- hosts.add(healthyInstance);
ServiceInfo infoWithHealthyInstance = new ServiceInfo();
- infoWithHealthyInstance.setHosts(hosts);
+ infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
when(proxy.queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(
infoWithHealthyInstance);
String serviceName = "service1";
String groupName = "group1";
//when
- client.selectOneHealthyInstance(serviceName, groupName, false);
+ Instance instance = client.selectOneHealthyInstance(serviceName, groupName, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, groupName, "", false);
+ assertNotNull(instance);
}
@Test
- void testSelectOneHealthyInstance5() throws NacosException {
+ void testSelectOneHealthyInstanceWithServiceAndClusters() throws NacosException {
//given
- Instance healthyInstance = new Instance();
- healthyInstance.setIp("1.1.1.1");
- healthyInstance.setPort(1000);
- List hosts = new ArrayList<>();
- hosts.add(healthyInstance);
ServiceInfo infoWithHealthyInstance = new ServiceInfo();
- infoWithHealthyInstance.setHosts(hosts);
- when(proxy.subscribe(anyString(), anyString(), anyString())).thenReturn(infoWithHealthyInstance);
-
+ infoWithHealthyInstance.addHost(mockInstance("cluster1", true));
+ infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
String serviceName = "service1";
+ when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, StringUtils.EMPTY)).thenReturn(
+ infoWithHealthyInstance);
List clusterList = Arrays.asList("cluster1", "cluster2");
//when
- client.selectOneHealthyInstance(serviceName, clusterList);
+ Instance instance = client.selectOneHealthyInstance(serviceName, clusterList);
//then
- verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, "cluster1,cluster2");
+ assertNotNull(instance);
+ assertEquals("cluster1", instance.getClusterName());
}
@Test
- void testSelectOneHealthyInstance6() throws NacosException {
+ void testSelectOneHealthyInstanceWithFullNameAndClusters() throws NacosException {
//given
- Instance healthyInstance = new Instance();
- healthyInstance.setIp("1.1.1.1");
- healthyInstance.setPort(1000);
- List hosts = new ArrayList<>();
- hosts.add(healthyInstance);
ServiceInfo infoWithHealthyInstance = new ServiceInfo();
- infoWithHealthyInstance.setHosts(hosts);
+ infoWithHealthyInstance.addHost(mockInstance("cluster1", true));
+ infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));
when(proxy.subscribe(anyString(), anyString(), anyString())).thenReturn(infoWithHealthyInstance);
String serviceName = "service1";
String groupName = "group1";
List clusterList = Arrays.asList("cluster1", "cluster2");
//when
- client.selectOneHealthyInstance(serviceName, groupName, clusterList);
+ Instance instance = client.selectOneHealthyInstance(serviceName, groupName, clusterList);
//then
- verify(proxy, times(1)).subscribe(serviceName, groupName, "cluster1,cluster2");
-
+ assertNotNull(instance);
+ assertEquals("cluster1", instance.getClusterName());
}
@Test
- void testSelectOneHealthyInstance7() throws NacosException {
+ void testSelectOneHealthyInstanceWithServiceAndClustersNotSubscribe() throws NacosException {
//given
- Instance healthyInstance = new Instance();
- healthyInstance.setIp("1.1.1.1");
- healthyInstance.setPort(1000);
- List hosts = new ArrayList<>();
- hosts.add(healthyInstance);
ServiceInfo infoWithHealthyInstance = new ServiceInfo();
- infoWithHealthyInstance.setHosts(hosts);
+ infoWithHealthyInstance.addHost(mockInstance("cluster1", true));
when(proxy.queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(
infoWithHealthyInstance);
String serviceName = "service1";
List clusterList = Arrays.asList("cluster1", "cluster2");
//when
- client.selectOneHealthyInstance(serviceName, clusterList, false);
+ Instance instance = client.selectOneHealthyInstance(serviceName, clusterList, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, "cluster1,cluster2",
- false);
+ assertNotNull(instance);
+ assertEquals("cluster1", instance.getClusterName());
}
@Test
- void testSelectOneHealthyInstance8() throws NacosException {
+ void testSelectOneHealthyInstanceWithFullNameAndClustersNotSubscribe() throws NacosException {
//given
- Instance healthyInstance = new Instance();
- healthyInstance.setIp("1.1.1.1");
- healthyInstance.setPort(1000);
- List hosts = new ArrayList<>();
- hosts.add(healthyInstance);
ServiceInfo infoWithHealthyInstance = new ServiceInfo();
- infoWithHealthyInstance.setHosts(hosts);
+ infoWithHealthyInstance.addHost(mockInstance("cluster1", true));
when(proxy.queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(
infoWithHealthyInstance);
@@ -789,13 +867,14 @@ void testSelectOneHealthyInstance8() throws NacosException {
String groupName = "group1";
List clusterList = Arrays.asList("cluster1", "cluster2");
//when
- client.selectOneHealthyInstance(serviceName, groupName, clusterList, false);
+ Instance instance = client.selectOneHealthyInstance(serviceName, groupName, clusterList, false);
//then
- verify(proxy, times(1)).queryInstancesOfService(serviceName, groupName, "cluster1,cluster2", false);
+ assertNotNull(instance);
+ assertEquals("cluster1", instance.getClusterName());
}
@Test
- void testSubscribe1() throws NacosException {
+ void testSubscribeOnlyService() throws NacosException {
//given
String serviceName = "service1";
EventListener listener = event -> {
@@ -811,7 +890,7 @@ void testSubscribe1() throws NacosException {
}
@Test
- void testSubscribe2() throws NacosException {
+ void testSubscribeFullName() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -828,7 +907,7 @@ void testSubscribe2() throws NacosException {
}
@Test
- void testSubscribe3() throws NacosException {
+ void testSubscribeWithServiceAndClusters() throws NacosException {
//given
String serviceName = "service1";
List clusterList = Arrays.asList("cluster1", "cluster2");
@@ -845,7 +924,7 @@ void testSubscribe3() throws NacosException {
}
@Test
- void testSubscribe4() throws NacosException {
+ void testSubscribeWithFullNameAndClusters() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -863,7 +942,22 @@ void testSubscribe4() throws NacosException {
}
@Test
- public void testSubscribe5() throws NacosException {
+ public void testSubscribeWithServiceAndCustomSelector() throws NacosException {
+ String serviceName = "service1";
+ EventListener listener = event -> {
+
+ };
+ //when
+ client.subscribe(serviceName, NamingSelectorFactory.HEALTHY_SELECTOR, listener);
+ NamingSelectorWrapper wrapper = new NamingSelectorWrapper(serviceName, Constants.DEFAULT_GROUP, Constants.NULL,
+ NamingSelectorFactory.HEALTHY_SELECTOR, listener);
+ //then
+ verify(changeNotifier, times(1)).registerListener(Constants.DEFAULT_GROUP, serviceName, wrapper);
+ verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, Constants.NULL);
+ }
+
+ @Test
+ public void testSubscribeWithFullNameAndCustomSelector() throws NacosException {
String serviceName = "service1";
String groupName = "group1";
EventListener listener = event -> {
@@ -892,7 +986,19 @@ void testSubscribeWithNullListener() throws NacosException {
}
@Test
- void testUnSubscribe1() throws NacosException {
+ void testSubscribeDuplicate() throws NacosException {
+ String serviceName = "service1";
+ when(changeNotifier.isSubscribed(Constants.DEFAULT_GROUP, serviceName)).thenReturn(true);
+ ServiceInfo serviceInfo = new ServiceInfo(Constants.DEFAULT_GROUP + "@@" + serviceName);
+ serviceInfo.addHost(new Instance());
+ when(serviceInfoHolder.getServiceInfo(serviceName, Constants.DEFAULT_GROUP, "")).thenReturn(serviceInfo);
+ final AtomicBoolean flag = new AtomicBoolean(false);
+ client.subscribe(serviceName, event -> flag.set(true));
+ assertTrue(flag.get());
+ }
+
+ @Test
+ void testUnSubscribeOnlyService() throws NacosException {
//given
String serviceName = "service1";
EventListener listener = event -> {
@@ -909,7 +1015,7 @@ void testUnSubscribe1() throws NacosException {
}
@Test
- void testUnSubscribe2() throws NacosException {
+ void testUnSubscribeFullName() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -928,7 +1034,7 @@ void testUnSubscribe2() throws NacosException {
}
@Test
- void testUnSubscribe3() throws NacosException {
+ void testUnSubscribeWithServiceAndClusters() throws NacosException {
//given
String serviceName = "service1";
List clusterList = Arrays.asList("cluster1", "cluster2");
@@ -947,7 +1053,7 @@ void testUnSubscribe3() throws NacosException {
}
@Test
- void testUnSubscribe4() throws NacosException {
+ void testUnSubscribeWithFullNameAndClusters() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -967,7 +1073,24 @@ void testUnSubscribe4() throws NacosException {
}
@Test
- public void testUnSubscribe5() throws NacosException {
+ public void testUnSubscribeWithServiceAndCustomSelector() throws NacosException {
+ //given
+ String serviceName = "service1";
+ EventListener listener = event -> {
+
+ };
+ when(changeNotifier.isSubscribed(Constants.DEFAULT_GROUP, serviceName)).thenReturn(false);
+
+ //when
+ client.unsubscribe(serviceName, NamingSelectorFactory.HEALTHY_SELECTOR, listener);
+ NamingSelectorWrapper wrapper = new NamingSelectorWrapper(NamingSelectorFactory.HEALTHY_SELECTOR, listener);
+ //then
+ verify(changeNotifier, times(1)).deregisterListener(Constants.DEFAULT_GROUP, serviceName, wrapper);
+ verify(proxy, times(1)).unsubscribe(serviceName, Constants.DEFAULT_GROUP, Constants.NULL);
+ }
+
+ @Test
+ public void testUnSubscribeWithFullNameAndCustomSelector() throws NacosException {
//given
String serviceName = "service1";
String groupName = "group1";
@@ -984,6 +1107,19 @@ public void testUnSubscribe5() throws NacosException {
verify(proxy, times(1)).unsubscribe(serviceName, groupName, Constants.NULL);
}
+ @Test
+ void testUnSubscribeWithNullListener() throws NacosException {
+ String serviceName = "service1";
+ String groupName = "group1";
+ //when
+ client.unsubscribe(serviceName, groupName, null);
+ //then
+ verify(changeNotifier, never()).deregisterListener(groupName, serviceName,
+ new NamingSelectorWrapper(NamingSelectorFactory.newIpSelector(""), null));
+ verify(proxy, never()).unsubscribe(serviceName, groupName, "");
+
+ }
+
@Test
void testGetServicesOfServer1() throws NacosException {
//given
@@ -1091,4 +1227,11 @@ void testConstructorWithServerList() throws NacosException, NoSuchFieldException
namingService.shutDown();
}
}
+
+ private Instance mockInstance(String clusterName, boolean healthy) {
+ Instance instance = new Instance();
+ instance.setClusterName(clusterName);
+ instance.setHealthy(healthy);
+ return instance;
+ }
}
\ No newline at end of file
diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxyTest.java b/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxyTest.java
index 62314db5473..bdb9472cfbc 100644
--- a/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxyTest.java
+++ b/client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxyTest.java
@@ -709,4 +709,21 @@ void testConfigAppNameLabels() throws Exception {
String appName = config.labels().get(Constants.APPNAME);
assertNotNull(appName);
}
+
+ @Test
+ void testResponseCode403Exception() throws NacosException {
+ Throwable exception = assertThrows(NacosException.class, () -> {
+
+ when(this.rpcClient.request(Mockito.any())).thenReturn(ErrorResponse.build(403, "Invalid signature"));
+
+ try {
+ client.registerService(SERVICE_NAME, GROUP_NAME, instance);
+ } catch (NacosException ex) {
+ assertNull(ex.getCause());
+
+ throw ex;
+ }
+ });
+ assertTrue(exception.getMessage().contains("Invalid signature"));
+ }
}
diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxyTest.java b/client/src/test/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxyTest.java
index dc0fccc2681..4cebc7f72de 100644
--- a/client/src/test/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxyTest.java
+++ b/client/src/test/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxyTest.java
@@ -645,4 +645,29 @@ void testRegApiForDomain() throws NacosException {
});
}
+
+ @Test
+ void testCallServerFail403() throws Exception {
+ //given
+ NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);
+
+ when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenAnswer(invocationOnMock -> {
+ //return url
+ HttpRestResult