From e56c5ac4d9d9310df372d1896bdf6dc2384b9c00 Mon Sep 17 00:00:00 2001
From: daizhenyu <1449308021@qq.com>
Date: Wed, 15 May 2024 15:50:19 +0800
Subject: [PATCH] xds base class and interface
Signed-off-by: daizhenyu <1449308021@qq.com>
---
pom.xml | 2 +-
.../config/config.properties | 11 ++
.../sermant/core/service/ServiceConfig.java | 14 +++
.../sermant/core/service/ServiceManager.java | 8 +-
.../core/service/xds/config/XdsConfig.java | 74 +++++++++++
.../service/xds/entity/ServiceInstance.java | 69 +++++++++++
.../listener/XdsServiceDiscoveryListener.java | 37 ++++++
.../java/io/sermant/core/utils/FileUtils.java | 24 ++++
.../io.sermant.core.config.common.BaseConfig | 1 +
.../sermant-agentcore-implement/pom.xml | 21 ++++
.../service/xds/cache/XdsDataCache.java | 80 ++++++++++++
.../xds/entity/XdsServiceInstance.java | 117 ++++++++++++++++++
.../service/xds/env/XdsConstant.java | 73 +++++++++++
.../service/xds/handler/XdsServiceAction.java | 35 ++++++
14 files changed, 564 insertions(+), 2 deletions(-)
create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/config/XdsConfig.java
create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/entity/ServiceInstance.java
create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/listener/XdsServiceDiscoveryListener.java
create mode 100644 sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/cache/XdsDataCache.java
create mode 100644 sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/entity/XdsServiceInstance.java
create mode 100644 sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/env/XdsConstant.java
create mode 100644 sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/handler/XdsServiceAction.java
diff --git a/pom.xml b/pom.xml
index c1a109800c..394f3e5824 100644
--- a/pom.xml
+++ b/pom.xml
@@ -73,7 +73,7 @@
3.3.0
3.2.4
2.5.3
- 1.36.1
+ 1.52.1
1.5.0.Final
0.5.1
2.8.1
diff --git a/sermant-agentcore/sermant-agentcore-config/config/config.properties b/sermant-agentcore/sermant-agentcore-config/config/config.properties
index 4d2c6fe0f6..50ad9c2b08 100644
--- a/sermant-agentcore/sermant-agentcore-config/config/config.properties
+++ b/sermant-agentcore/sermant-agentcore-config/config/config.properties
@@ -28,6 +28,8 @@ agent.service.inject.enable=true
agent.service.dynamic.config.enable=true
# HTTP server switch
agent.service.httpserver.enable=false
+# xDS service switch
+agent.service.xds.service.enable=false
#============================= Event configuration =============================#
# Event switch
event.enable=false
@@ -85,6 +87,15 @@ gateway.nettyPort=6888
#gateway.initReconnectInternalTime=5
# Specify retreat algorithm maximum connection interval (s)
#gateway.maxReconnectInternalTime=180
+#=============================xds configuration===============================#
+# istio control plane address
+xds.config.control.plane.address=istiod.istio-system.svc:15010
+# Whether to use secure communication with the control plane
+xds.config.security.enable=false
+# Certificates used for secure communication with the control plane
+xds.config.certificate.path=
+# Private key used for secure communication with the control plane
+xds.config.private.key.path=
#=============================Metadata===============================#
# Service name for host service instance
service.meta.service=default
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/ServiceConfig.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/ServiceConfig.java
index a9c7afa4ff..087c1d31e0 100644
--- a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/ServiceConfig.java
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/ServiceConfig.java
@@ -46,6 +46,9 @@ public class ServiceConfig implements BaseConfig {
@ConfigFieldKey("httpserver.enable")
private boolean httpserverEnable = false;
+ @ConfigFieldKey("xds.service.enable")
+ private boolean xdsServiceEnable = false;
+
public boolean isHeartBeatEnable() {
return heartBeatEnable;
}
@@ -94,6 +97,14 @@ public void setHttpserverEnable(boolean httpserverEnable) {
this.httpserverEnable = httpserverEnable;
}
+ public boolean isXdsServiceEnable() {
+ return xdsServiceEnable;
+ }
+
+ public void setXdsServiceEnable(boolean xdsServiceEnable) {
+ this.xdsServiceEnable = xdsServiceEnable;
+ }
+
/**
* Check whether the service of the given class name is enabled.
*
@@ -119,6 +130,9 @@ public boolean checkServiceEnable(String serviceName) {
if (ServiceManager.HTTP_SERVER_SERVICE_IMPL.equals(serviceName)) {
return isHttpserverEnable();
}
+ if (ServiceManager.XDS_SERVICE_IMPL.equals(serviceName)) {
+ return isXdsServiceEnable();
+ }
return false;
}
}
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/ServiceManager.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/ServiceManager.java
index fc2f7edeb6..bbd565bb50 100644
--- a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/ServiceManager.java
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/ServiceManager.java
@@ -79,11 +79,17 @@ public class ServiceManager {
"io.sermant.implement.service.tracing.TracingServiceImpl";
/**
- * HttpServer服务类名
+ * HttpServer service name
*/
public static final String HTTP_SERVER_SERVICE_IMPL =
"io.sermant.implement.service.httpserver.HttpServerServiceImpl";
+ /**
+ * xDS Service Discover
+ */
+ public static final String XDS_SERVICE_IMPL =
+ "io.sermant.implement.service.xds.XdsServiceImpl";
+
/**
* logger
*/
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/config/XdsConfig.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/config/XdsConfig.java
new file mode 100644
index 0000000000..86f3370b4a
--- /dev/null
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/config/XdsConfig.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
+ *
+ * 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 io.sermant.core.service.xds.config;
+
+import io.sermant.core.config.common.BaseConfig;
+import io.sermant.core.config.common.ConfigFieldKey;
+import io.sermant.core.config.common.ConfigTypeKey;
+
+/**
+ * XdsConfig
+ *
+ * @author daizhenyu
+ * @since 2024-05-08
+ **/
+@ConfigTypeKey("xds.config")
+public class XdsConfig implements BaseConfig {
+ @ConfigFieldKey("control.plane.address")
+ private String controlPlaneAddress;
+
+ @ConfigFieldKey("security.enable")
+ private boolean securityEnable = false;
+
+ @ConfigFieldKey("certificate.path")
+ private String certificatePath;
+
+ @ConfigFieldKey("private.key.path")
+ private String privateKeyPath;
+
+ public String getControlPlaneAddress() {
+ return controlPlaneAddress;
+ }
+
+ public void setControlPlaneAddress(String controlPlaneAddress) {
+ this.controlPlaneAddress = controlPlaneAddress;
+ }
+
+ public boolean isSecurityEnable() {
+ return securityEnable;
+ }
+
+ public void setSecurityEnable(boolean securityEnable) {
+ this.securityEnable = securityEnable;
+ }
+
+ public String getCertificatePath() {
+ return certificatePath;
+ }
+
+ public void setCertificatePath(String certificatePath) {
+ this.certificatePath = certificatePath;
+ }
+
+ public String getPrivateKeyPath() {
+ return privateKeyPath;
+ }
+
+ public void setPrivateKeyPath(String privateKeyPath) {
+ this.privateKeyPath = privateKeyPath;
+ }
+}
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/entity/ServiceInstance.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/entity/ServiceInstance.java
new file mode 100644
index 0000000000..c902c6ca47
--- /dev/null
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/entity/ServiceInstance.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
+ *
+ * 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 io.sermant.core.service.xds.entity;
+
+import java.util.Map;
+
+/**
+ * service instance interface
+ *
+ * @author daizhenyu
+ * @since 2024-05-09
+ **/
+public interface ServiceInstance {
+ /**
+ * get xds cluster name
+ *
+ * @return cluster name
+ */
+ String getClusterName();
+
+ /**
+ * get service name
+ *
+ * @return service name
+ */
+ String getServiceName();
+
+ /**
+ * get service instance host
+ *
+ * @return service instance host
+ */
+ String getHost();
+
+ /**
+ * get service instance port
+ *
+ * @return service instance port
+ */
+ int getPort();
+
+ /**
+ * get service instance metadata
+ *
+ * @return metadata
+ */
+ Map getMetaData();
+
+ /**
+ * get service instance health status
+ *
+ * @return service instance health status
+ */
+ boolean isHealthy();
+}
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/listener/XdsServiceDiscoveryListener.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/listener/XdsServiceDiscoveryListener.java
new file mode 100644
index 0000000000..1d13007cce
--- /dev/null
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/service/xds/listener/XdsServiceDiscoveryListener.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
+ *
+ * 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 io.sermant.core.service.xds.listener;
+
+import io.sermant.core.service.xds.entity.ServiceInstance;
+
+import java.util.EventListener;
+import java.util.Set;
+
+/**
+ * XdsServiceListener
+ *
+ * @author daizhenyu
+ * @since 2024-05-08
+ **/
+public interface XdsServiceDiscoveryListener extends EventListener {
+ /**
+ * Process the updated service instance
+ *
+ * @param instances updated service instance
+ */
+ void process(Set instances);
+}
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/FileUtils.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/FileUtils.java
index d02f446ccb..a1ce45eed1 100644
--- a/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/FileUtils.java
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/io/sermant/core/utils/FileUtils.java
@@ -23,6 +23,10 @@
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.logging.Level;
import java.util.logging.Logger;
/**
@@ -192,6 +196,26 @@ public boolean accept(File dir, String name) {
});
}
+ /**
+ * read file and convert it to string
+ *
+ * @param filePath file path
+ * @return String
+ */
+ public static String readFileToString(String filePath) {
+ // Read all bytes from the file at once
+ byte[] bytes = null;
+ try {
+ bytes = Files.readAllBytes(Paths.get(filePath));
+ } catch (IOException e) {
+ LOGGER.log(Level.SEVERE, "cannot read file content, please check the path");
+ return StringUtils.EMPTY;
+ }
+
+ // Convert the bytes to a String using UTF-8 encoding
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+
private static boolean matchFileByWildcard(String name, String[] wcs) {
for (String wc : wcs) {
if (StringUtils.isWildcardMatch(name, wc)) {
diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/resources/META-INF/services/io.sermant.core.config.common.BaseConfig b/sermant-agentcore/sermant-agentcore-core/src/main/resources/META-INF/services/io.sermant.core.config.common.BaseConfig
index 59629d4218..8dc8e371d9 100644
--- a/sermant-agentcore/sermant-agentcore-core/src/main/resources/META-INF/services/io.sermant.core.config.common.BaseConfig
+++ b/sermant-agentcore/sermant-agentcore-core/src/main/resources/META-INF/services/io.sermant.core.config.common.BaseConfig
@@ -9,3 +9,4 @@ io.sermant.core.service.send.config.GatewayConfig
io.sermant.core.plugin.config.ServiceMeta
io.sermant.core.notification.config.NotificationConfig
io.sermant.core.service.httpserver.config.HttpServerConfig
+io.sermant.core.service.xds.config.XdsConfig
diff --git a/sermant-agentcore/sermant-agentcore-implement/pom.xml b/sermant-agentcore/sermant-agentcore-implement/pom.xml
index 88b247b5aa..9717eea432 100644
--- a/sermant-agentcore/sermant-agentcore-implement/pom.xml
+++ b/sermant-agentcore/sermant-agentcore-implement/pom.xml
@@ -30,6 +30,7 @@
1.6.7
2.1.2
2.13.4.2
+ 0.1.32
@@ -125,6 +126,26 @@
asm-commons
${asm.version}
+
+ io.envoyproxy.controlplane
+ api
+ ${envoyproxy.controlplane.version}
+
+
+ io.grpc
+ grpc-netty
+ ${grpc.version}
+
+
+ io.grpc
+ grpc-stub
+ ${grpc.version}
+
+
+ io.grpc
+ grpc-protobuf
+ ${grpc.version}
+
junit
junit
diff --git a/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/cache/XdsDataCache.java b/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/cache/XdsDataCache.java
new file mode 100644
index 0000000000..5747ee0a69
--- /dev/null
+++ b/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/cache/XdsDataCache.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
+ *
+ * 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 io.sermant.implement.service.xds.cache;
+
+import io.envoyproxy.envoy.service.discovery.v3.DiscoveryRequest;
+import io.grpc.stub.StreamObserver;
+import io.sermant.core.service.xds.entity.ServiceInstance;
+import io.sermant.core.service.xds.listener.XdsServiceDiscoveryListener;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * xDS data cache
+ *
+ * @author daizhenyu
+ * @since 2024-05-09
+ **/
+public class XdsDataCache {
+ /**
+ * key:service name value:instances
+ */
+ public static final Map> SERVICE_INSTANCES =
+ new ConcurrentHashMap<>();
+
+ /**
+ * key:service name value:listener list
+ */
+ public static final Map> SERVICE_DISCOVER_LISTENER =
+ new ConcurrentHashMap<>();
+
+ /**
+ * request StreamObserver
+ */
+ public static final Map> REQUEST_OBSERVERS = new ConcurrentHashMap<>();
+
+ /**
+ * key:service name value:cluster map
+ */
+ private static Map> serviceNameMapping;
+
+ private XdsDataCache() {
+ }
+
+ /**
+ * update the mapping between service and cluster
+ *
+ * @param mapping the mapping between service and cluster
+ */
+ public static void updateServiceNameMapping(Map> mapping) {
+ serviceNameMapping = mapping;
+ }
+
+ /**
+ * get cluster list for service
+ *
+ * @param serviceName
+ * @return cluster list for service
+ */
+ public static List getClustersByServiceName(String serviceName) {
+ return serviceNameMapping.getOrDefault(serviceName, Collections.EMPTY_LIST);
+ }
+}
\ No newline at end of file
diff --git a/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/entity/XdsServiceInstance.java b/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/entity/XdsServiceInstance.java
new file mode 100644
index 0000000000..a5dd96b564
--- /dev/null
+++ b/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/entity/XdsServiceInstance.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
+ *
+ * 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 io.sermant.implement.service.xds.entity;
+
+import io.sermant.core.service.xds.entity.ServiceInstance;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * XdsServiceInstance
+ *
+ * @author daizhenyu
+ * @since 2024-05-10
+ **/
+public class XdsServiceInstance implements ServiceInstance {
+ private String cluster;
+
+ private String service;
+
+ private String address;
+
+ private int port;
+
+ private boolean healthStatus;
+
+ private Map metadata;
+
+ @Override
+ public String getClusterName() {
+ return cluster;
+ }
+
+ @Override
+ public String getServiceName() {
+ return service;
+ }
+
+ @Override
+ public String getHost() {
+ return service;
+ }
+
+ @Override
+ public int getPort() {
+ return port;
+ }
+
+ @Override
+ public Map getMetaData() {
+ return metadata;
+ }
+
+ @Override
+ public boolean isHealthy() {
+ return healthStatus;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ XdsServiceInstance instance = (XdsServiceInstance) obj;
+ return port == instance.port && healthStatus == instance.healthStatus
+ && Objects.equals(cluster, instance.cluster)
+ && Objects.equals(service, instance.service)
+ && Objects.equals(address, instance.address)
+ && Objects.equals(metadata, instance.metadata);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(cluster, service, address, port, healthStatus, metadata);
+ }
+
+ public void setCluster(String cluster) {
+ this.cluster = cluster;
+ }
+
+ public void setService(String service) {
+ this.service = service;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public void setHealthStatus(boolean healthStatus) {
+ this.healthStatus = healthStatus;
+ }
+
+ public void setMetadata(Map metadata) {
+ this.metadata = metadata;
+ }
+}
diff --git a/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/env/XdsConstant.java b/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/env/XdsConstant.java
new file mode 100644
index 0000000000..4a76b1d41e
--- /dev/null
+++ b/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/env/XdsConstant.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
+ *
+ * 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 io.sermant.implement.service.xds.env;
+
+/**
+ * Constant
+ *
+ * @author daizhenyu
+ * @since 2024-05-09
+ **/
+public class XdsConstant {
+ /**
+ * pod name environment
+ */
+ public static final String POD_NAME_ENV = "HOSTNAME";
+
+ /**
+ * rsa key size
+ */
+ public static final int RSA_KEY_SIZE = 2048;
+
+ /**
+ * eds resource type
+ */
+ public static final String EDS_RESOURCE_TYPE = "envoy.config.endpoint.v3.ClusterLoadAssignment";
+
+ /**
+ * cds resource type
+ */
+ public static final String CDS_RESOURCE_TYPE = "envoy.config.cluster.v3.Cluster";
+
+ /**
+ * sidecar string
+ */
+ public static final String SIDECAR = "sidecar";
+
+ /**
+ * ~ string
+ */
+ public static final String WAVY_LINE = "~";
+
+ /**
+ * . string
+ */
+ public static final String POINT = ".";
+
+ /**
+ * hots suffix of k8s
+ */
+ public static final String HOST_SUFFIX = "svc.cluster.local";
+
+ /**
+ * cds request cache key for subscribe all resource
+ */
+ public static final String CDS_ALL_RESOURCE = "CLUSTER_ALL";
+
+ private XdsConstant() {
+ }
+}
diff --git a/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/handler/XdsServiceAction.java b/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/handler/XdsServiceAction.java
new file mode 100644
index 0000000000..602d3083b8
--- /dev/null
+++ b/sermant-agentcore/sermant-agentcore-implement/src/main/java/io/sermant/implement/service/xds/handler/XdsServiceAction.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
+ *
+ * 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 io.sermant.implement.service.xds.handler;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Xds handler interface to subscribe resource from istiod
+ *
+ * @author daizhenyu
+ * @since 2024-05-14
+ **/
+public interface XdsServiceAction {
+ /**
+ * subscribe
+ *
+ * @param resourceKey resource key to get the xds data from cache
+ * @param countDownLatch Used to notify the xds requesting thread to obtain data
+ */
+ void subscribe(String resourceKey, CountDownLatch countDownLatch);
+}