This is an automated email from the ASF dual-hosted git repository.

zhongxjian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-kubernetes.git


The following commit(s) were added to refs/heads/master by this push:
     new 95b12ddf update status and metadata api (#837)
95b12ddf is described below

commit 95b12ddfbb49d6b0807ede45a4278bb249cf5d3c
Author: mfordjody <[email protected]>
AuthorDate: Wed Dec 31 20:37:40 2025 +0800

    update status and metadata api (#837)
---
 api/annotation/annotations.gen.go                  | 158 +++++++
 api/annotation/annotations.yaml                    |  53 +++
 api/label/labels.gen.go                            | 214 +++++++++
 api/label/labels.yaml                              |  71 +++
 api/meta/v1alpha1/status.pb.go                     | 221 ++++++++++
 api/meta/v1alpha1/status.proto                     |  41 ++
 api/meta/v1alpha1/status_json.gen.go               |  34 ++
 api/networking/v1alpha3/destination_rule.proto     |  15 +
 api/networking/v1alpha3/virtual_service.proto      |  15 +
 api/security/v1alpha3/authorization_policy.proto   |  15 +
 api/security/v1alpha3/ca.proto                     |  15 +
 api/security/v1alpha3/peer_authentication.proto    |  15 +
 api/security/v1alpha3/request_authentication.proto |  15 +
 dubbod/planet/pkg/bootstrap/config_controller.go   |  16 +-
 dubbod/planet/pkg/bootstrap/server.go              |  10 +-
 dubbod/planet/pkg/config/kube/crdclient/client.go  |   4 +-
 dubbod/planet/pkg/config/kube/crdclient/types.go   |  66 +--
 dubbod/planet/pkg/features/experimental.go         |   4 +-
 .../model/{subsetrule.go => destinationrule.go}    |  14 +-
 dubbod/planet/pkg/model/push_context.go            | 100 ++---
 dubbod/planet/pkg/model/service.go                 |  39 --
 dubbod/planet/pkg/networking/grpcgen/cds.go        |   4 +-
 .../serviceregistry/kube/controller/controller.go  |   3 +-
 .../kube/controller/endpointslice.go               |  13 +-
 .../pkg/serviceregistry/kube/controller/pod.go     |  10 +-
 .../planet/pkg/serviceregistry/kube/conversion.go  |  78 ----
 .../planet/pkg/serviceregistry/util/label/label.go |  44 +-
 dubbod/planet/pkg/xds/cds.go                       |   8 +-
 go.mod                                             |   1 +
 go.sum                                             |   2 +
 manifests/charts/base/files/crd-all.yaml           |  18 +-
 pkg/adsc/adsc.go                                   | 129 +-----
 pkg/adsc/util.go                                   |  22 -
 pkg/config/schema/collections/collections.agent.go |  34 +-
 pkg/config/schema/collections/collections.go       |  34 +-
 pkg/config/schema/gvk/resources.go                 |  10 +-
 pkg/config/schema/gvr/resources.go                 |   4 +-
 pkg/config/schema/kind/resources.go                |   6 +-
 pkg/config/schema/kubeclient/resources.go          |  22 +-
 pkg/config/schema/kubetypes/resources.go           |   2 +-
 pkg/kube/inject/inject.go                          |  16 +-
 pkg/kube/inject/webhook.go                         |  38 +-
 samples/grpc-app/README.md                         |  14 +-
 tests/grpc-app/consumer/main.go                    |  14 +-
 tools/metadata/main.go                             | 485 +++++++++++++++++++++
 45 files changed, 1598 insertions(+), 548 deletions(-)

diff --git a/api/annotation/annotations.gen.go 
b/api/annotation/annotations.gen.go
new file mode 100644
index 00000000..cfa91f72
--- /dev/null
+++ b/api/annotation/annotations.gen.go
@@ -0,0 +1,158 @@
+
+// GENERATED FILE -- DO NOT EDIT
+
+package annotation
+
+type FeatureStatus int
+
+const (
+       Alpha FeatureStatus = iota
+       Beta
+       Stable
+)
+
+func (s FeatureStatus) String() string {
+       switch s {
+       case Alpha:
+               return "Alpha"
+       case Beta:
+               return "Beta"
+       case Stable:
+               return "Stable"
+       }
+       return "Unknown"
+}
+
+type ResourceTypes int
+
+const (
+       Unknown ResourceTypes = iota
+    Pod
+)
+
+func (r ResourceTypes) String() string {
+       switch r {
+       case 1:
+               return "Pod"
+       }
+       return "Unknown"
+}
+
+// Instance describes a single resource annotation
+type Instance struct {
+       // The name of the annotation.
+       Name string
+
+       // Description of the annotation.
+       Description string
+
+       // FeatureStatus of this annotation.
+       FeatureStatus FeatureStatus
+
+       // Hide the existence of this annotation when outputting usage 
information.
+       Hidden bool
+
+       // Mark this annotation as deprecated when generating usage information.
+       Deprecated bool
+
+       // The types of resources this annotation applies to.
+       Resources []ResourceTypes
+}
+
+var (
+
+       OrgApacheDubboRev = Instance {
+               Name:          "dubbo.apache.org/rev",
+               Description:   "Specifies a control plane revision to which a 
given proxy "+
+                        "is connected. This annotation is added automatically, 
not "+
+                        "set by a user. In contrary to the label "+
+                        "dubbo.apache.org/rev, it represents the actual 
revision, "+
+                        "not the requested revision.",
+               FeatureStatus: Alpha,
+               Hidden:        false,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Pod,
+               },
+       }
+
+       OrgApacheDubboInjectTemplates = Instance {
+               Name:          "inject.dubbo.apache.org/templates",
+               Description:   "The name of the inject template(s) to use, as a 
comma "+
+                        "separate list.",
+               FeatureStatus: Alpha,
+               Hidden:        false,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Pod,
+               },
+       }
+
+       OrgApacheDubboProxyConfig = Instance {
+               Name:          "proxy.dubbo.apache.org/config",
+               Description:   "Overrides for the proxy configuration for this 
specific "+
+                        "proxy.",
+               FeatureStatus: Beta,
+               Hidden:        false,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Pod,
+               },
+       }
+
+       OrgApacheDubboProxyOverrides = Instance {
+               Name:          "proxy.dubbo.apache.org/overrides",
+               Description:   "Used internally to indicate user-specified 
overrides in "+
+                        "the proxy container of the pod during injection.",
+               FeatureStatus: Alpha,
+               Hidden:        true,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Pod,
+               },
+       }
+
+       OrgApacheDubboProxylessInject = Instance {
+               Name:          "proxyless.dubbo.apache.org/inject",
+               Description:   "Specifies whether or not an proxyless adapter 
should be "+
+                        "automatically injected into the workload.",
+               FeatureStatus: Alpha,
+               Hidden:        false,
+               Deprecated:    true,
+               Resources: []ResourceTypes{
+                       Pod,
+               },
+       }
+
+       OrgApacheDubboProxylessStatus = Instance {
+               Name:          "proxyless.dubbo.apache.org/status",
+               Description:   "Generated by proxyless adapter injection that 
indicates "+
+                        "the status of the operation. Includes a version hash 
of "+
+                        "the executed template, as well as names of injected "+
+                        "resources.",
+               FeatureStatus: Alpha,
+               Hidden:        false,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Pod,
+               },
+       }
+
+)
+
+func AllResourceAnnotations() []*Instance {
+       return []*Instance {
+               &OrgApacheDubboRev,
+               &OrgApacheDubboInjectTemplates,
+               &OrgApacheDubboProxyConfig,
+               &OrgApacheDubboProxyOverrides,
+               &OrgApacheDubboProxylessInject,
+               &OrgApacheDubboProxylessStatus,
+       }
+}
+
+func AllResourceTypes() []string {
+       return []string {
+               "Pod",
+       }
+}
diff --git a/api/annotation/annotations.yaml b/api/annotation/annotations.yaml
new file mode 100644
index 00000000..ab42b771
--- /dev/null
+++ b/api/annotation/annotations.yaml
@@ -0,0 +1,53 @@
+annotations:
+  - name: proxyless.dubbo.apache.org/inject
+    featureStatus: Alpha
+    description: Specifies whether or not an proxyless adapter should be 
automatically
+      injected into the workload.
+    deprecated: true
+    hidden: false
+    resources:
+      - Pod
+
+  - name: proxyless.dubbo.apache.org/status
+    featureStatus: Alpha
+    description: Generated by proxyless adapter injection that indicates the 
status of
+      the operation. Includes a version hash of the executed template, as well 
as names of
+      injected resources.
+    deprecated: false
+    hidden: false
+    resources:
+      - Pod
+
+  - name: proxy.dubbo.apache.org/config
+    featureStatus: Beta
+    description: Overrides for the proxy configuration for this specific proxy.
+    deprecated: false
+    hidden: false
+    resources:
+      - Pod
+
+  - name: dubbo.apache.org/rev
+    featureStatus: Alpha
+    description: Specifies a control plane revision to which a given proxy is 
connected.
+      This annotation is added automatically, not set by a user. In contrary 
to the label dubbo.apache.org/rev,
+      it represents the actual revision, not the requested revision.
+    deprecated: false
+    hidden: false
+    resources:
+      - Pod
+
+  - name: proxy.dubbo.apache.org/overrides
+    featureStatus: Alpha
+    description: Used internally to indicate user-specified overrides in the 
proxy container of the pod during injection.
+    deprecated: false
+    hidden: true
+    resources:
+      - Pod
+
+  - name: inject.dubbo.apache.org/templates
+    featureStatus: Alpha
+    description: The name of the inject template(s) to use, as a comma 
separate list.
+    deprecated: false
+    hidden: false
+    resources:
+      - Pod
diff --git a/api/label/labels.gen.go b/api/label/labels.gen.go
new file mode 100644
index 00000000..0d7ba4b9
--- /dev/null
+++ b/api/label/labels.gen.go
@@ -0,0 +1,214 @@
+
+// GENERATED FILE -- DO NOT EDIT
+
+package label
+
+type FeatureStatus int
+
+const (
+       Alpha FeatureStatus = iota
+       Beta
+       Stable
+)
+
+func (s FeatureStatus) String() string {
+       switch s {
+       case Alpha:
+               return "Alpha"
+       case Beta:
+               return "Beta"
+       case Stable:
+               return "Stable"
+       }
+       return "Unknown"
+}
+
+type ResourceTypes int
+
+const (
+       Unknown ResourceTypes = iota
+    Any
+    Deployment
+    Gateway
+    HorizontalPodAutoscaler
+    Namespace
+    Pod
+    PodDisruptionBudget
+    Service
+    ServiceAccount
+)
+
+func (r ResourceTypes) String() string {
+       switch r {
+       case 1:
+               return "Any"
+       case 2:
+               return "Deployment"
+       case 3:
+               return "Gateway"
+       case 4:
+               return "HorizontalPodAutoscaler"
+       case 5:
+               return "Namespace"
+       case 6:
+               return "Pod"
+       case 7:
+               return "PodDisruptionBudget"
+       case 8:
+               return "Service"
+       case 9:
+               return "ServiceAccount"
+       }
+       return "Unknown"
+}
+
+// Instance describes a single resource label
+type Instance struct {
+       // The name of the label.
+       Name string
+
+       // Description of the label.
+       Description string
+
+       // FeatureStatus of this label.
+       FeatureStatus FeatureStatus
+
+       // Hide the existence of this label when outputting usage information.
+       Hidden bool
+
+       // Mark this label as deprecated when generating usage information.
+       Deprecated bool
+
+       // The types of resources this label applies to.
+       Resources []ResourceTypes
+}
+
+var (
+
+       OrgApacheDubboRev = Instance {
+               Name:          "dubbo.apache.org/rev",
+               Description:   "Dubbo control plane revision or tag associated 
with the "+
+                        "resource; e.g. `canary`",
+               FeatureStatus: Beta,
+               Hidden:        false,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Namespace,
+                       Gateway,
+                       Pod,
+               },
+       }
+
+       IoK8sNetworkingGatewayGatewayClassName = Instance {
+               Name:          "gateway.networking.k8s.io/gateway-class-name",
+               Description:   "Automatically added to all resources 
[automatically "+
+                        
"created](/docs/tasks/traffic-management/ingress/gateway-api/#automated-deployment)
 "+
+                        "by Dubbo Gateway controller to indicate which "+
+                        "`GatewayClass` resulted in the object creation. Users 
"+
+                        "should not set this label themselves.",
+               FeatureStatus: Stable,
+               Hidden:        false,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       ServiceAccount,
+                       Deployment,
+                       Service,
+                       PodDisruptionBudget,
+                       HorizontalPodAutoscaler,
+               },
+       }
+
+       IoK8sNetworkingGatewayGatewayName = Instance {
+               Name:          "gateway.networking.k8s.io/gateway-name",
+               Description:   "Automatically added to all resources 
[automatically "+
+                        
"created](/docs/tasks/traffic-management/ingress/gateway-api/#automated-deployment)
 "+
+                        "by Dubbo Gateway controller to indicate which 
`Gateway` "+
+                        "resulted in the object creation. Users should not set 
"+
+                        "this label themselves.",
+               FeatureStatus: Stable,
+               Hidden:        false,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       ServiceAccount,
+                       Deployment,
+                       Service,
+                       PodDisruptionBudget,
+                       HorizontalPodAutoscaler,
+               },
+       }
+
+       OrgApacheDubboOperatorComponent = Instance {
+               Name:          "operator.dubbo.apache.org/component",
+               Description:   "Dubbo operator component name of the resource, 
e.g. "+
+                        "`Pilot`",
+               FeatureStatus: Alpha,
+               Hidden:        true,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Any,
+               },
+       }
+
+       OrgApacheDubboOperatorManaged = Instance {
+               Name:          "operator.dubbo.apache.org/managed",
+               Description:   "Set to `Reconcile` if the Dubbo operator will 
reconcile "+
+                        "the resource.",
+               FeatureStatus: Alpha,
+               Hidden:        true,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Any,
+               },
+       }
+
+       OrgApacheDubboOperatorVersion = Instance {
+               Name:          "operator.dubbo.apache.org/version",
+               Description:   "The Dubbo operator version that installed the 
resource, "+
+                        "e.g. `1.6.0`",
+               FeatureStatus: Alpha,
+               Hidden:        true,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Any,
+               },
+       }
+
+       OrgApacheDubboProxylessInject = Instance {
+               Name:          "proxyless.dubbo.apache.org/inject",
+               Description:   "Specifies whether or not an proxyless adapter 
should be "+
+                        "automatically injected into the workload.",
+               FeatureStatus: Alpha,
+               Hidden:        false,
+               Deprecated:    false,
+               Resources: []ResourceTypes{
+                       Pod,
+               },
+       }
+
+)
+
+func AllResourceLabels() []*Instance {
+       return []*Instance {
+               &OrgApacheDubboRev,
+               &IoK8sNetworkingGatewayGatewayClassName,
+               &IoK8sNetworkingGatewayGatewayName,
+               &OrgApacheDubboOperatorComponent,
+               &OrgApacheDubboOperatorManaged,
+               &OrgApacheDubboOperatorVersion,
+               &OrgApacheDubboProxylessInject,
+       }
+}
+
+func AllResourceTypes() []string {
+       return []string {
+               "Any",
+               "Deployment",
+               "Gateway",
+               "HorizontalPodAutoscaler",
+               "Namespace",
+               "Pod",
+               "PodDisruptionBudget",
+               "Service",
+               "ServiceAccount",
+       }
+}
diff --git a/api/label/labels.yaml b/api/label/labels.yaml
new file mode 100644
index 00000000..9f04ae5b
--- /dev/null
+++ b/api/label/labels.yaml
@@ -0,0 +1,71 @@
+labels:
+  - name: dubbo.apache.org/rev
+    featureStatus: Beta
+    description: Dubbo control plane revision or tag associated with the 
resource; e.g. `canary`
+    hidden: false
+    deprecated: false
+    resources:
+      - Namespace
+      - Gateway
+      - Pod
+
+  - name: operator.dubbo.apache.org/component
+    featureStatus: Alpha
+    description: Dubbo operator component name of the resource, e.g. `Pilot`
+    hidden: true
+    deprecated: false
+    resources:
+      - Any
+
+  - name: operator.dubbo.apache.org/managed
+    featureStatus: Alpha
+    description: Set to `Reconcile` if the Dubbo operator will reconcile the 
resource.
+    hidden: true
+    deprecated: false
+    resources:
+      - Any
+
+  - name: operator.dubbo.apache.org/version
+    featureStatus: Alpha
+    description: The Dubbo operator version that installed the resource, e.g. 
`1.6.0`
+    hidden: true
+    deprecated: false
+    resources:
+      - Any
+
+  - name: proxyless.dubbo.apache.org/inject
+    featureStatus: Alpha
+    description: Specifies whether or not an proxyless adapter should be 
automatically
+      injected into the workload.
+    deprecated: false
+    hidden: false
+    resources:
+      - Pod
+
+
+  - name: gateway.networking.k8s.io/gateway-name
+    featureStatus: Stable
+    description: Automatically added to all resources [automatically 
created](/docs/tasks/traffic-management/ingress/gateway-api/#automated-deployment)
+      by Dubbo Gateway controller to indicate which `Gateway` resulted in the 
object creation. Users should not set this label themselves.
+    deprecated: false
+    hidden: false
+    resources:
+      - ServiceAccount
+      - Deployment
+      - Service
+      - PodDisruptionBudget
+      - HorizontalPodAutoscaler
+
+  - name: gateway.networking.k8s.io/gateway-class-name
+    featureStatus: Stable
+    description: Automatically added to all resources [automatically 
created](/docs/tasks/traffic-management/ingress/gateway-api/#automated-deployment)
+      by Dubbo Gateway controller to indicate which `GatewayClass` resulted in 
the object creation. Users should not set this label themselves.
+    deprecated: false
+    hidden: false
+    resources:
+      - ServiceAccount
+      - Deployment
+      - Service
+      - PodDisruptionBudget
+      - HorizontalPodAutoscaler
+
diff --git a/api/meta/v1alpha1/status.pb.go b/api/meta/v1alpha1/status.pb.go
new file mode 100644
index 00000000..047ec446
--- /dev/null
+++ b/api/meta/v1alpha1/status.pb.go
@@ -0,0 +1,221 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+//     protoc-gen-go v1.36.10
+//     protoc        v6.33.0
+// source: status.proto
+
+package v1alpha1
+
+import (
+       protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+       protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+       reflect "reflect"
+       sync "sync"
+       unsafe "unsafe"
+)
+
+const (
+       // Verify that this generated code is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+       // Verify that runtime/protoimpl is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type DubboStatus struct {
+       state protoimpl.MessageState `protogen:"open.v1"`
+       // +optional
+       // +patchMergeKey=type
+       // +patchStrategy=merge
+       Conditions    []*DubboCondition 
`protobuf:"bytes,1,rep,name=conditions,proto3" json:"conditions,omitempty"`
+       unknownFields protoimpl.UnknownFields
+       sizeCache     protoimpl.SizeCache
+}
+
+func (x *DubboStatus) Reset() {
+       *x = DubboStatus{}
+       mi := &file_status_proto_msgTypes[0]
+       ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+       ms.StoreMessageInfo(mi)
+}
+
+func (x *DubboStatus) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DubboStatus) ProtoMessage() {}
+
+func (x *DubboStatus) ProtoReflect() protoreflect.Message {
+       mi := &file_status_proto_msgTypes[0]
+       if x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use DubboStatus.ProtoReflect.Descriptor instead.
+func (*DubboStatus) Descriptor() ([]byte, []int) {
+       return file_status_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *DubboStatus) GetConditions() []*DubboCondition {
+       if x != nil {
+               return x.Conditions
+       }
+       return nil
+}
+
+type DubboCondition struct {
+       state  protoimpl.MessageState `protogen:"open.v1"`
+       Type   string                 `protobuf:"bytes,1,opt,name=type,proto3" 
json:"type,omitempty"`
+       Status string                 
`protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
+       // +optional
+       Reason string `protobuf:"bytes,3,opt,name=reason,proto3" 
json:"reason,omitempty"`
+       // +optional
+       // +protoc-gen-crd:validation:XIntOrString
+       ObservedGeneration int64 
`protobuf:"varint,4,opt,name=observed_generation,json=observedGeneration,proto3"
 json:"observed_generation,omitempty"`
+       unknownFields      protoimpl.UnknownFields
+       sizeCache          protoimpl.SizeCache
+}
+
+func (x *DubboCondition) Reset() {
+       *x = DubboCondition{}
+       mi := &file_status_proto_msgTypes[1]
+       ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+       ms.StoreMessageInfo(mi)
+}
+
+func (x *DubboCondition) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DubboCondition) ProtoMessage() {}
+
+func (x *DubboCondition) ProtoReflect() protoreflect.Message {
+       mi := &file_status_proto_msgTypes[1]
+       if x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use DubboCondition.ProtoReflect.Descriptor instead.
+func (*DubboCondition) Descriptor() ([]byte, []int) {
+       return file_status_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *DubboCondition) GetType() string {
+       if x != nil {
+               return x.Type
+       }
+       return ""
+}
+
+func (x *DubboCondition) GetStatus() string {
+       if x != nil {
+               return x.Status
+       }
+       return ""
+}
+
+func (x *DubboCondition) GetReason() string {
+       if x != nil {
+               return x.Reason
+       }
+       return ""
+}
+
+func (x *DubboCondition) GetObservedGeneration() int64 {
+       if x != nil {
+               return x.ObservedGeneration
+       }
+       return 0
+}
+
+var File_status_proto protoreflect.FileDescriptor
+
+const file_status_proto_rawDesc = "" +
+       "\n" +
+       "\fstatus.proto\x12\x13dubbo.meta.v1alpha1\"R\n" +
+       "\vDubboStatus\x12C\n" +
+       "\n" +
+       "conditions\x18\x01 \x03(\v2#.dubbo.meta.v1alpha1.DubboConditionR\n" +
+       "conditions\"\x85\x01\n" +
+       "\x0eDubboCondition\x12\x12\n" +
+       "\x04type\x18\x01 \x01(\tR\x04type\x12\x16\n" +
+       "\x06status\x18\x02 \x01(\tR\x06status\x12\x16\n" +
+       "\x06reason\x18\x03 \x01(\tR\x06reason\x12/\n" +
+       "\x13observed_generation\x18\x04 
\x01(\x03R\x12observedGenerationB\x14Z\x12/api/meta/v1alpha1b\x06proto3"
+
+var (
+       file_status_proto_rawDescOnce sync.Once
+       file_status_proto_rawDescData []byte
+)
+
+func file_status_proto_rawDescGZIP() []byte {
+       file_status_proto_rawDescOnce.Do(func() {
+               file_status_proto_rawDescData = 
protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_status_proto_rawDesc),
 len(file_status_proto_rawDesc)))
+       })
+       return file_status_proto_rawDescData
+}
+
+var file_status_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_status_proto_goTypes = []any{
+       (*DubboStatus)(nil),    // 0: dubbo.meta.v1alpha1.DubboStatus
+       (*DubboCondition)(nil), // 1: dubbo.meta.v1alpha1.DubboCondition
+}
+var file_status_proto_depIdxs = []int32{
+       1, // 0: dubbo.meta.v1alpha1.DubboStatus.conditions:type_name -> 
dubbo.meta.v1alpha1.DubboCondition
+       1, // [1:1] is the sub-list for method output_type
+       1, // [1:1] is the sub-list for method input_type
+       1, // [1:1] is the sub-list for extension type_name
+       1, // [1:1] is the sub-list for extension extendee
+       0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_status_proto_init() }
+func file_status_proto_init() {
+       if File_status_proto != nil {
+               return
+       }
+       type x struct{}
+       out := protoimpl.TypeBuilder{
+               File: protoimpl.DescBuilder{
+                       GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+                       RawDescriptor: 
unsafe.Slice(unsafe.StringData(file_status_proto_rawDesc), 
len(file_status_proto_rawDesc)),
+                       NumEnums:      0,
+                       NumMessages:   2,
+                       NumExtensions: 0,
+                       NumServices:   0,
+               },
+               GoTypes:           file_status_proto_goTypes,
+               DependencyIndexes: file_status_proto_depIdxs,
+               MessageInfos:      file_status_proto_msgTypes,
+       }.Build()
+       File_status_proto = out.File
+       file_status_proto_goTypes = nil
+       file_status_proto_depIdxs = nil
+}
diff --git a/api/meta/v1alpha1/status.proto b/api/meta/v1alpha1/status.proto
new file mode 100644
index 00000000..5c1b164d
--- /dev/null
+++ b/api/meta/v1alpha1/status.proto
@@ -0,0 +1,41 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package dubbo.meta.v1alpha1;
+
+option go_package = "/api/meta/v1alpha1";
+
+message DubboStatus {
+  // +optional
+  // +patchMergeKey=type
+  // +patchStrategy=merge
+  repeated DubboCondition conditions = 1;
+}
+
+message DubboCondition {
+  string type = 1;
+
+  string status = 2;
+
+  // +optional
+  string reason = 3;
+
+  // +optional
+  // +protoc-gen-crd:validation:XIntOrString
+  int64 observed_generation = 4;
+}
diff --git a/api/meta/v1alpha1/status_json.gen.go 
b/api/meta/v1alpha1/status_json.gen.go
new file mode 100644
index 00000000..3c2e1260
--- /dev/null
+++ b/api/meta/v1alpha1/status_json.gen.go
@@ -0,0 +1,34 @@
+// Code generated by protoc-gen-jsonshim. DO NOT EDIT.
+package v1alpha1
+
+import (
+       bytes "bytes"
+       jsonpb "github.com/golang/protobuf/jsonpb"
+)
+
+// MarshalJSON is a custom marshaler for DubboStatus
+func (this *DubboStatus) MarshalJSON() ([]byte, error) {
+       str, err := StatusMarshaler.MarshalToString(this)
+       return []byte(str), err
+}
+
+// UnmarshalJSON is a custom unmarshaler for DubboStatus
+func (this *DubboStatus) UnmarshalJSON(b []byte) error {
+       return StatusUnmarshaler.Unmarshal(bytes.NewReader(b), this)
+}
+
+// MarshalJSON is a custom marshaler for DubboCondition
+func (this *DubboCondition) MarshalJSON() ([]byte, error) {
+       str, err := StatusMarshaler.MarshalToString(this)
+       return []byte(str), err
+}
+
+// UnmarshalJSON is a custom unmarshaler for DubboCondition
+func (this *DubboCondition) UnmarshalJSON(b []byte) error {
+       return StatusUnmarshaler.Unmarshal(bytes.NewReader(b), this)
+}
+
+var (
+       StatusMarshaler   = &jsonpb.Marshaler{}
+       StatusUnmarshaler = &jsonpb.Unmarshaler{AllowUnknownFields: true}
+)
diff --git a/api/networking/v1alpha3/destination_rule.proto 
b/api/networking/v1alpha3/destination_rule.proto
new file mode 100644
index 00000000..a6f66394
--- /dev/null
+++ b/api/networking/v1alpha3/destination_rule.proto
@@ -0,0 +1,15 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
\ No newline at end of file
diff --git a/api/networking/v1alpha3/virtual_service.proto 
b/api/networking/v1alpha3/virtual_service.proto
new file mode 100644
index 00000000..a6f66394
--- /dev/null
+++ b/api/networking/v1alpha3/virtual_service.proto
@@ -0,0 +1,15 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
\ No newline at end of file
diff --git a/api/security/v1alpha3/authorization_policy.proto 
b/api/security/v1alpha3/authorization_policy.proto
new file mode 100644
index 00000000..a6f66394
--- /dev/null
+++ b/api/security/v1alpha3/authorization_policy.proto
@@ -0,0 +1,15 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
\ No newline at end of file
diff --git a/api/security/v1alpha3/ca.proto b/api/security/v1alpha3/ca.proto
new file mode 100644
index 00000000..a6f66394
--- /dev/null
+++ b/api/security/v1alpha3/ca.proto
@@ -0,0 +1,15 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
\ No newline at end of file
diff --git a/api/security/v1alpha3/peer_authentication.proto 
b/api/security/v1alpha3/peer_authentication.proto
new file mode 100644
index 00000000..a6f66394
--- /dev/null
+++ b/api/security/v1alpha3/peer_authentication.proto
@@ -0,0 +1,15 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
\ No newline at end of file
diff --git a/api/security/v1alpha3/request_authentication.proto 
b/api/security/v1alpha3/request_authentication.proto
new file mode 100644
index 00000000..a6f66394
--- /dev/null
+++ b/api/security/v1alpha3/request_authentication.proto
@@ -0,0 +1,15 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
\ No newline at end of file
diff --git a/dubbod/planet/pkg/bootstrap/config_controller.go 
b/dubbod/planet/pkg/bootstrap/config_controller.go
index ff77ac5d..2777e567 100644
--- a/dubbod/planet/pkg/bootstrap/config_controller.go
+++ b/dubbod/planet/pkg/bootstrap/config_controller.go
@@ -178,9 +178,12 @@ func (s *Server) initConfigSources(args *PlanetArgs) (err 
error) {
                        s.ConfigStores = append(s.ConfigStores, 
configController)
                        log.Infof("Started File configSource %s", 
configSource.Address)
                case XDS:
+                       // XDS config source support (legacy - MCP protocol 
removed)
+                       // Note: MCP was a legacy protocol replaced by 
APIGenerator in Istio
+                       // This XDS config source may not be needed for 
proxyless mesh
                        // TLS settings removed from ConfigSource - use 
insecure credentials
                        // TODO: Implement TLS support when needed
-                       xdsMCP, err := adsc.New(srcAddress.Host, 
&adsc.ADSConfig{
+                       xdsClient, err := adsc.New(srcAddress.Host, 
&adsc.ADSConfig{
                                InitialDiscoveryRequests: 
adsc.ConfigInitialRequests(),
                                Config: adsc.Config{
                                        Namespace: args.Namespace,
@@ -199,11 +202,11 @@ func (s *Server) initConfigSources(args *PlanetArgs) (err 
error) {
                        store := memory.Make(collections.Planet)
                        // TODO: enable namespace filter for memory controller
                        configController := memory.NewController(store)
-                       
configController.RegisterHasSyncedHandler(xdsMCP.HasSynced)
-                       xdsMCP.Store = configController
-                       err = xdsMCP.Run()
+                       
configController.RegisterHasSyncedHandler(xdsClient.HasSynced)
+                       xdsClient.Store = configController
+                       err = xdsClient.Run()
                        if err != nil {
-                               return fmt.Errorf("MCP: failed running %v", err)
+                               return fmt.Errorf("XDS config source: failed 
running %v", err)
                        }
                        s.ConfigStores = append(s.ConfigStores, 
configController)
                        log.Infof("Started XDS configSource %s", 
configSource.Address)
@@ -230,7 +233,8 @@ func (s *Server) initConfigSources(args *PlanetArgs) (err 
error) {
 func (s *Server) initConfigController(args *PlanetArgs) error {
        meshGlobalConfig := s.environment.Mesh()
        if len(meshGlobalConfig.ConfigSources) > 0 {
-               // Using MCP for config.
+               // XDS config source support (legacy - MCP protocol removed)
+               // Note: MCP was a legacy protocol replaced by APIGenerator in 
Istio
                if err := s.initConfigSources(args); err != nil {
                        return err
                }
diff --git a/dubbod/planet/pkg/bootstrap/server.go 
b/dubbod/planet/pkg/bootstrap/server.go
index 046e3282..556d2d5b 100644
--- a/dubbod/planet/pkg/bootstrap/server.go
+++ b/dubbod/planet/pkg/bootstrap/server.go
@@ -491,8 +491,8 @@ func (s *Server) initRegistryEventHandlers() {
 
                var configKind kind.Kind
                switch schemaID {
-               case "SubsetRule":
-                       configKind = kind.SubsetRule
+               case "DestinationRule":
+                       configKind = kind.DestinationRule
                case "serviceRoute", "ServiceRoute":
                        configKind = kind.ServiceRoute
                case "PeerAuthentication":
@@ -517,18 +517,18 @@ func (s *Server) initRegistryEventHandlers() {
                // Log the config change
                log.Infof("configHandler: %s event for %s/%s/%s", event, 
configKey.Kind, configKey.Namespace, configKey.Name)
 
-               // Some configs 
(SubsetRule/ServiceRoute/PeerAuthentication/HTTPRoute) require Full push to 
ensure
+               // Some configs 
(DestinationRule/ServiceRoute/PeerAuthentication/HTTPRoute) require Full push 
to ensure
                // PushContext is re-initialized and configuration is reloaded.
                // PeerAuthentication must rebuild AuthenticationPolicies to 
enable STRICT mTLS on LDS; without
                // a full push the cached PushContext would continue serving 
plaintext listeners.
                // HTTPRoute must rebuild HTTPRoute index to enable Gateway API 
routing.
-               needsFullPush := configKind == kind.SubsetRule || configKind == 
kind.ServiceRoute || configKind == kind.PeerAuthentication || configKind == 
kind.HTTPRoute
+               needsFullPush := configKind == kind.DestinationRule || 
configKind == kind.ServiceRoute || configKind == kind.PeerAuthentication || 
configKind == kind.HTTPRoute
 
                // Trigger ConfigUpdate to push changes to all connected proxies
                s.XDSServer.ConfigUpdate(&model.PushRequest{
                        ConfigsUpdated: sets.New(configKey),
                        Reason:         
model.NewReasonStats(model.DependentResource),
-                       Full:           needsFullPush, // Full push for 
SubsetRule/ServiceRoute to reload PushContext
+                       Full:           needsFullPush, // Full push for 
DestinationRule/ServiceRoute to reload PushContext
                })
        }
        schemas := collections.Planet.All()
diff --git a/dubbod/planet/pkg/config/kube/crdclient/client.go 
b/dubbod/planet/pkg/config/kube/crdclient/client.go
index fe04e088..d5a361f7 100644
--- a/dubbod/planet/pkg/config/kube/crdclient/client.go
+++ b/dubbod/planet/pkg/config/kube/crdclient/client.go
@@ -206,10 +206,10 @@ func (cl *Client) addCRD(name string, opts 
krt.OptionsBuilder) {
        if s.IsBuiltin() {
                kc = kclient.NewUntypedInformer(cl.client, gvr, filter)
        } else {
-               // For SubsetRule and ServiceRoute, we use Dynamic client which 
returns unstructured objects
+               // For DestinationRule and ServiceRoute, we use Dynamic client 
which returns unstructured objects
                // So we need to use DynamicInformer type to ensure the 
informer expects unstructured objects
                informerType := kubetypes.StandardInformer
-               if resourceGVK == gvk.SubsetRule || resourceGVK == 
gvk.ServiceRoute || resourceGVK == gvk.PeerAuthentication {
+               if resourceGVK == gvk.DestinationRule || resourceGVK == 
gvk.ServiceRoute || resourceGVK == gvk.PeerAuthentication {
                        informerType = kubetypes.DynamicInformer
                        cl.logger.Debugf("addCRD: using DynamicInformer for %v 
(uses Dynamic client)", resourceGVK)
                }
diff --git a/dubbod/planet/pkg/config/kube/crdclient/types.go 
b/dubbod/planet/pkg/config/kube/crdclient/types.go
index dc34fa2a..59895f25 100644
--- a/dubbod/planet/pkg/config/kube/crdclient/types.go
+++ b/dubbod/planet/pkg/config/kube/crdclient/types.go
@@ -21,11 +21,11 @@ import (
        "context"
        "fmt"
 
+       dubboapimetav1alpha1 
"github.com/apache/dubbo-kubernetes/api/meta/v1alpha1"
        "github.com/apache/dubbo-kubernetes/pkg/config"
        "github.com/apache/dubbo-kubernetes/pkg/config/schema/gvk"
        "github.com/apache/dubbo-kubernetes/pkg/kube"
        "github.com/apache/dubbo-kubernetes/pkg/util/protomarshal"
-       istioioapimetav1alpha1 "istio.io/api/meta/v1alpha1"
        istioioapinetworkingv1alpha3 "istio.io/api/networking/v1alpha3"
        istioioapisecurityv1beta1 "istio.io/api/security/v1beta1"
        apiistioioapinetworkingv1 "istio.io/client-go/pkg/apis/networking/v1"
@@ -54,8 +54,8 @@ func assignSpec[T any](dst *T, src *T) {
 
 func create(c kube.Client, cfg config.Config, objMeta metav1.ObjectMeta) 
(metav1.Object, error) {
        switch cfg.GroupVersionKind {
-       case gvk.SubsetRule:
-               // SubsetRule uses networking.dubbo.apache.org API group, not 
networking.istio.io
+       case gvk.DestinationRule:
+               // DestinationRule uses networking.dubbo.apache.org API group, 
not networking.istio.io
                // Use Dynamic client to access it, but reuse Istio's 
DestinationRule spec structure
                spec := cfg.Spec.(*istioioapinetworkingv1alpha3.DestinationRule)
                clonedSpec := protomarshal.Clone(spec)
@@ -71,13 +71,13 @@ func create(c kube.Client, cfg config.Config, objMeta 
metav1.ObjectMeta) (metav1
                u := &unstructured.Unstructured{Object: uObj}
                u.SetGroupVersionKind(schema.GroupVersionKind{
                        Group:   "networking.dubbo.apache.org",
-                       Version: "v1",
-                       Kind:    "SubsetRule",
+                       Version: "v1alpha3",
+                       Kind:    "DestinationRule",
                })
                return c.Dynamic().Resource(schema.GroupVersionResource{
                        Group:    "networking.dubbo.apache.org",
-                       Version:  "v1",
-                       Resource: "subsetrules",
+                       Version:  "v1alpha3",
+                       Resource: "destinationrules",
                }).Namespace(cfg.Namespace).Create(context.TODO(), u, 
metav1.CreateOptions{})
        case gvk.PeerAuthentication:
                spec := cfg.Spec.(*istioioapisecurityv1beta1.PeerAuthentication)
@@ -148,8 +148,8 @@ func create(c kube.Client, cfg config.Config, objMeta 
metav1.ObjectMeta) (metav1
 
 func update(c kube.Client, cfg config.Config, objMeta metav1.ObjectMeta) 
(metav1.Object, error) {
        switch cfg.GroupVersionKind {
-       case gvk.SubsetRule:
-               // SubsetRule uses networking.dubbo.apache.org API group, use 
Dynamic client
+       case gvk.DestinationRule:
+               // DestinationRule uses networking.dubbo.apache.org API group, 
use Dynamic client
                spec := cfg.Spec.(*istioioapinetworkingv1alpha3.DestinationRule)
                clonedSpec := protomarshal.Clone(spec)
                obj := &apiistioioapinetworkingv1.DestinationRule{
@@ -163,13 +163,13 @@ func update(c kube.Client, cfg config.Config, objMeta 
metav1.ObjectMeta) (metav1
                u := &unstructured.Unstructured{Object: uObj}
                u.SetGroupVersionKind(schema.GroupVersionKind{
                        Group:   "networking.dubbo.apache.org",
-                       Version: "v1",
-                       Kind:    "SubsetRule",
+                       Version: "v1alpha3",
+                       Kind:    "DestinationRule",
                })
                return c.Dynamic().Resource(schema.GroupVersionResource{
                        Group:    "networking.dubbo.apache.org",
-                       Version:  "v1",
-                       Resource: "subsetrules",
+                       Version:  "v1alpha3",
+                       Resource: "destinationrules",
                }).Namespace(cfg.Namespace).Update(context.TODO(), u, 
metav1.UpdateOptions{})
        case gvk.PeerAuthentication:
                spec := cfg.Spec.(*istioioapisecurityv1beta1.PeerAuthentication)
@@ -238,9 +238,9 @@ func update(c kube.Client, cfg config.Config, objMeta 
metav1.ObjectMeta) (metav1
 
 func updateStatus(c kube.Client, cfg config.Config, objMeta metav1.ObjectMeta) 
(metav1.Object, error) {
        switch cfg.GroupVersionKind {
-       case gvk.SubsetRule:
-               // SubsetRule uses networking.dubbo.apache.org API group, use 
Dynamic client
-               status := cfg.Status.(*istioioapimetav1alpha1.IstioStatus)
+       case gvk.DestinationRule:
+               // DestinationRule uses networking.dubbo.apache.org API group, 
use Dynamic client
+               status := cfg.Status.(*dubboapimetav1alpha1.DubboStatus)
                clonedStatus := protomarshal.Clone(status)
                obj := &apiistioioapinetworkingv1.DestinationRule{
                        ObjectMeta: objMeta,
@@ -253,16 +253,16 @@ func updateStatus(c kube.Client, cfg config.Config, 
objMeta metav1.ObjectMeta) (
                u := &unstructured.Unstructured{Object: uObj}
                u.SetGroupVersionKind(schema.GroupVersionKind{
                        Group:   "networking.dubbo.apache.org",
-                       Version: "v1",
-                       Kind:    "SubsetRule",
+                       Version: "v1alpha3",
+                       Kind:    "DestinationRule",
                })
                return c.Dynamic().Resource(schema.GroupVersionResource{
                        Group:    "networking.dubbo.apache.org",
-                       Version:  "v1",
-                       Resource: "subsetrules",
+                       Version:  "v1alpha3",
+                       Resource: "destinationrules",
                }).Namespace(cfg.Namespace).UpdateStatus(context.TODO(), u, 
metav1.UpdateOptions{})
        case gvk.PeerAuthentication:
-               status := cfg.Status.(*istioioapimetav1alpha1.IstioStatus)
+               status := cfg.Status.(*dubboapimetav1alpha1.DubboStatus)
                clonedStatus := protomarshal.Clone(status)
                obj := &apiistioioapisecurityv1.PeerAuthentication{
                        ObjectMeta: objMeta,
@@ -285,7 +285,7 @@ func updateStatus(c kube.Client, cfg config.Config, objMeta 
metav1.ObjectMeta) (
                }).Namespace(cfg.Namespace).UpdateStatus(context.TODO(), u, 
metav1.UpdateOptions{})
        case gvk.ServiceRoute:
                // ServiceRoute uses networking.dubbo.apache.org API group, use 
Dynamic client
-               status := cfg.Status.(*istioioapimetav1alpha1.IstioStatus)
+               status := cfg.Status.(*dubboapimetav1alpha1.DubboStatus)
                clonedStatus := protomarshal.Clone(status)
                obj := &apiistioioapinetworkingv1.VirtualService{
                        ObjectMeta: objMeta,
@@ -331,8 +331,8 @@ func patch(c kube.Client, orig config.Config, origMeta 
metav1.ObjectMeta, mod co
                return nil, fmt.Errorf("gvk mismatch: %v, modified: %v", 
orig.GroupVersionKind, mod.GroupVersionKind)
        }
        switch orig.GroupVersionKind {
-       case gvk.SubsetRule:
-               // SubsetRule uses networking.dubbo.apache.org API group, use 
Dynamic client
+       case gvk.DestinationRule:
+               // DestinationRule uses networking.dubbo.apache.org API group, 
use Dynamic client
                origSpec := 
orig.Spec.(*istioioapinetworkingv1alpha3.DestinationRule)
                modSpec := 
mod.Spec.(*istioioapinetworkingv1alpha3.DestinationRule)
                clonedOrigSpec := protomarshal.Clone(origSpec)
@@ -351,8 +351,8 @@ func patch(c kube.Client, orig config.Config, origMeta 
metav1.ObjectMeta, mod co
                }
                return c.Dynamic().Resource(schema.GroupVersionResource{
                        Group:    "networking.dubbo.apache.org",
-                       Version:  "v1",
-                       Resource: "subsetrules",
+                       Version:  "v1alpha3",
+                       Resource: "destinationrules",
                }).Namespace(orig.Namespace).Patch(context.TODO(), orig.Name, 
typ, patchBytes, metav1.PatchOptions{FieldManager: "planet-discovery"})
        case gvk.PeerAuthentication:
                origSpec := 
orig.Spec.(*istioioapisecurityv1beta1.PeerAuthentication)
@@ -455,12 +455,12 @@ func delete(c kube.Client, typ config.GroupVersionKind, 
name, namespace string,
                deleteOptions.Preconditions = 
&metav1.Preconditions{ResourceVersion: resourceVersion}
        }
        switch typ {
-       case gvk.SubsetRule:
-               // SubsetRule uses networking.dubbo.apache.org API group, use 
Dynamic client
+       case gvk.DestinationRule:
+               // DestinationRule uses networking.dubbo.apache.org API group, 
use Dynamic client
                return c.Dynamic().Resource(schema.GroupVersionResource{
                        Group:    "networking.dubbo.apache.org",
-                       Version:  "v1",
-                       Resource: "subsetrules",
+                       Version:  "v1alpha3",
+                       Resource: "destinationrules",
                }).Namespace(namespace).Delete(context.TODO(), name, 
deleteOptions)
        case gvk.PeerAuthentication:
                return c.Dynamic().Resource(schema.GroupVersionResource{
@@ -559,7 +559,7 @@ var translationMap = map[config.GroupVersionKind]func(r 
runtime.Object) config.C
                        Spec: &obj.Spec,
                }
        },
-       gvk.SubsetRule: func(r runtime.Object) config.Config {
+       gvk.DestinationRule: func(r runtime.Object) config.Config {
                var obj *apiistioioapinetworkingv1.DestinationRule
                // Handle unstructured objects from Dynamic client
                // First try to convert from unstructured, as Dynamic client 
returns unstructured objects
@@ -583,12 +583,12 @@ var translationMap = map[config.GroupVersionKind]func(r 
runtime.Object) config.C
                                        panic(fmt.Sprintf("failed to convert 
object %T to DestinationRule: %v", r, err))
                                }
                        } else {
-                               panic(fmt.Sprintf("unexpected object type for 
SubsetRule: %T, expected *unstructured.Unstructured or 
*apiistioioapinetworkingv1.DestinationRule, conversion error: %v", r, err))
+                               panic(fmt.Sprintf("unexpected object type for 
DestinationRule: %T, expected *unstructured.Unstructured or 
*apiistioioapinetworkingv1.DestinationRule, conversion error: %v", r, err))
                        }
                }
                return config.Config{
                        Meta: config.Meta{
-                               GroupVersionKind:  gvk.SubsetRule,
+                               GroupVersionKind:  gvk.DestinationRule,
                                Name:              obj.Name,
                                Namespace:         obj.Namespace,
                                Labels:            obj.Labels,
diff --git a/dubbod/planet/pkg/features/experimental.go 
b/dubbod/planet/pkg/features/experimental.go
index ce09bff6..699de332 100644
--- a/dubbod/planet/pkg/features/experimental.go
+++ b/dubbod/planet/pkg/features/experimental.go
@@ -24,8 +24,8 @@ var (
        EnableLeaderElection = env.Register("ENABLE_LEADER_ELECTION", true,
                "If enabled (default), starts a leader election client and 
gains leadership before executing controllers. "+
                        "If false, it assumes that only one instance of dubbod 
is running and skips leader election.").Get()
-       EnableEnhancedSubsetRuleMerge = 
env.Register("ENABLE_ENHANCED_DESTINATIONRULE_MERGE", true,
-               "If enabled, Dubbo merge subsetrules considering their exportTo 
fields,"+
+       EnableEnhancedDestinationRuleMerge = 
env.Register("ENABLE_ENHANCED_DESTINATIONRULE_MERGE", true,
+               "If enabled, Dubbo merge destinationrules considering their 
exportTo fields,"+
                        " they will be kept as independent rules if the 
exportTos are not equal.").Get()
        EnableGatewayAPI = env.Register("PLANET_ENABLE_GATEWAY_API", true,
                "If this is set to true, support for Kubernetes gateway-api 
(github.com/kubernetes-sigs/gateway-api) will "+
diff --git a/dubbod/planet/pkg/model/subsetrule.go 
b/dubbod/planet/pkg/model/destinationrule.go
similarity index 88%
rename from dubbod/planet/pkg/model/subsetrule.go
rename to dubbod/planet/pkg/model/destinationrule.go
index 7d92f477..cb409d40 100644
--- a/dubbod/planet/pkg/model/subsetrule.go
+++ b/dubbod/planet/pkg/model/destinationrule.go
@@ -27,7 +27,7 @@ import (
        "k8s.io/apimachinery/pkg/types"
 )
 
-func (ps *PushContext) mergeSubsetRule(p *consolidatedSubRules, subRuleConfig 
config.Config, exportToSet sets.Set[visibility.Instance]) {
+func (ps *PushContext) mergeDestinationRule(p *consolidatedSubRules, 
subRuleConfig config.Config, exportToSet sets.Set[visibility.Instance]) {
        rule := subRuleConfig.Spec.(*networking.DestinationRule)
        resolvedHost := host.Name(rule.Host)
 
@@ -40,11 +40,11 @@ func (ps *PushContext) mergeSubsetRule(p 
*consolidatedSubRules, subRuleConfig co
        }
 
        if mdrList, exists := subRules[resolvedHost]; exists {
-               log.Infof("mergeSubsetRule: found existing rules for host %s 
(count: %d)", resolvedHost, len(mdrList))
+               log.Infof("mergeDestinationRule: found existing rules for host 
%s (count: %d)", resolvedHost, len(mdrList))
                // `appendSeparately` determines if the incoming destination 
rule would become a new unique entry in the processedDestRules list.
                appendSeparately := true
                for _, mdr := range mdrList {
-                       if features.EnableEnhancedSubsetRuleMerge {
+                       if features.EnableEnhancedDestinationRuleMerge {
                                if exportToSet.Equals(mdr.exportTo) {
                                        appendSeparately = false
                                } else if len(mdr.exportTo) > 0 && 
exportToSet.SupersetOf(mdr.exportTo) {
@@ -72,7 +72,7 @@ func (ps *PushContext) mergeSubsetRule(p 
*consolidatedSubRules, subRuleConfig co
                        // at the same time added as a unique entry in the 
processedDestRules.
                        if bothWithoutSelector || (bothWithSelector && 
selectorsMatch) {
                                appendSeparately = false
-                               log.Debugf("mergeSubsetRule: will merge rules 
for host %s (bothWithoutSelector: %v, bothWithSelector: %v, selectorsMatch: 
%v)",
+                               log.Debugf("mergeDestinationRule: will merge 
rules for host %s (bothWithoutSelector: %v, bothWithSelector: %v, 
selectorsMatch: %v)",
                                        resolvedHost, bothWithoutSelector, 
bothWithSelector, selectorsMatch)
                        }
 
@@ -99,7 +99,7 @@ func (ps *PushContext) mergeSubsetRule(p 
*consolidatedSubRules, subRuleConfig co
                        }
 
                        // Merge top-level traffic policy. Historically we only 
copied the first non-nil policy,
-                       // which meant a later SubsetRule that supplied TLS 
settings was ignored once a prior
+                       // which meant a later DestinationRule that supplied 
TLS settings was ignored once a prior
                        // rule (e.g. subsets only) existed. To match Istio's 
behavior and ensure Proxyless gRPC
                        // can enable mTLS after subsets are defined, allow the 
incoming rule to override the TLS
                        // portion even when a Common TrafficPolicy already 
exists.
@@ -107,14 +107,14 @@ func (ps *PushContext) mergeSubsetRule(p 
*consolidatedSubRules, subRuleConfig co
                                if mergedRule.TrafficPolicy == nil {
                                        // First rule with TrafficPolicy, copy 
it entirely
                                        mergedRule.TrafficPolicy = 
rule.TrafficPolicy
-                                       log.Infof("mergeSubsetRule: copied 
TrafficPolicy from new rule to merged rule for host %s (has TLS: %v)",
+                                       log.Infof("mergeDestinationRule: copied 
TrafficPolicy from new rule to merged rule for host %s (has TLS: %v)",
                                                resolvedHost, 
rule.TrafficPolicy.Tls != nil)
                                } else {
                                        // Merge TrafficPolicy fields, with TLS 
settings from the latest rule taking precedence
                                        if rule.TrafficPolicy.Tls != nil {
                                                // TLS settings from the latest 
rule always win (ISTIO_MUTUAL/DUBBO_MUTUAL)
                                                mergedRule.TrafficPolicy.Tls = 
rule.TrafficPolicy.Tls
-                                               log.Infof("mergeSubsetRule: 
updated TLS settings in merged TrafficPolicy for host %s (mode: %v)",
+                                               
log.Infof("mergeDestinationRule: updated TLS settings in merged TrafficPolicy 
for host %s (mode: %v)",
                                                        resolvedHost, 
rule.TrafficPolicy.Tls.Mode)
                                        }
                                        // Merge other TrafficPolicy fields if 
needed (loadBalancer, connectionPool, etc.)
diff --git a/dubbod/planet/pkg/model/push_context.go 
b/dubbod/planet/pkg/model/push_context.go
index f209cc03..22336fcc 100644
--- a/dubbod/planet/pkg/model/push_context.go
+++ b/dubbod/planet/pkg/model/push_context.go
@@ -77,7 +77,7 @@ type PushContext struct {
        ServiceIndex           serviceIndex
        serviceRouteIndex      serviceRouteIndex
        httpRouteIndex         httpRouteIndex
-       subsetRuleIndex        subsetRuleIndex
+       destinationRuleIndex        destinationRuleIndex
        serviceAccounts        map[serviceAccountKey][]string
        AuthenticationPolicies *AuthenticationPolicies
        PushVersion            string
@@ -141,7 +141,7 @@ type ConsolidatedSubRule struct {
 type exportToDefaults struct {
        service      sets.Set[visibility.Instance]
        serviceRoute sets.Set[visibility.Instance]
-       subsetRule   sets.Set[visibility.Instance]
+       destinationRule   sets.Set[visibility.Instance]
 }
 
 type serviceRouteIndex struct {
@@ -160,7 +160,7 @@ type httpRouteIndex struct {
        hostToRoutes map[host.Name][]config.Config
 }
 
-type subsetRuleIndex struct {
+type destinationRuleIndex struct {
        namespaceLocal      map[string]*consolidatedSubRules
        exportedByNamespace map[string]*consolidatedSubRules
        rootNamespaceLocal  *consolidatedSubRules
@@ -175,7 +175,7 @@ func NewPushContext() *PushContext {
        return &PushContext{
                ServiceIndex:      newServiceIndex(),
                serviceRouteIndex: newServiceRouteIndex(),
-               subsetRuleIndex:   newSubsetRuleIndex(),
+               destinationRuleIndex:   newDestinationRuleIndex(),
                serviceAccounts:   map[serviceAccountKey][]string{},
        }
 }
@@ -199,8 +199,8 @@ func newServiceRouteIndex() serviceRouteIndex {
        return out
 }
 
-func newSubsetRuleIndex() subsetRuleIndex {
-       return subsetRuleIndex{
+func newDestinationRuleIndex() destinationRuleIndex {
+       return destinationRuleIndex{
                namespaceLocal:      map[string]*consolidatedSubRules{},
                exportedByNamespace: map[string]*consolidatedSubRules{},
        }
@@ -315,14 +315,14 @@ func (pr *PushRequest) PushReason() string {
 }
 
 func (ps *PushContext) initDefaultExportMaps() {
-       ps.exportToDefaults.subsetRule = sets.New[visibility.Instance]()
+       ps.exportToDefaults.destinationRule = sets.New[visibility.Instance]()
        if ps.Mesh.DefaultDestinationRuleExportTo != nil {
                for _, e := range ps.Mesh.DefaultDestinationRuleExportTo {
-                       
ps.exportToDefaults.subsetRule.Insert(visibility.Instance(e))
+                       
ps.exportToDefaults.destinationRule.Insert(visibility.Instance(e))
                }
        } else {
                // default to *
-               ps.exportToDefaults.subsetRule.Insert(visibility.Public)
+               ps.exportToDefaults.destinationRule.Insert(visibility.Public)
        }
 
        ps.exportToDefaults.service = sets.New[visibility.Instance]()
@@ -532,7 +532,7 @@ func (ps *PushContext) createNewContext(env *Environment) {
        ps.initKubernetesGateways(env)
        ps.initServiceRoutes(env)
        ps.initHTTPRoutes(env)
-       ps.initSubsetRules(env)
+       ps.initDestinationRules(env)
        ps.initAuthenticationPolicies(env)
 }
 
@@ -562,27 +562,27 @@ func (ps *PushContext) updateContext(env *Environment, 
oldPushContext *PushConte
                }
        }
 
-       // Check if subsetRules have changed base on:
-       // 1. SubsetRule updates in ConfigsUpdated
+       // Check if destinationrules have changed base on:
+       // 1. DestinationRule updates in ConfigsUpdated
        // 2. Full push (Full: true) - always re-initialize on full push
-       subsetRulesChanged := pushReq != nil && (pushReq.Full || 
HasConfigsOfKind(pushReq.ConfigsUpdated, kind.SubsetRule) ||
+               destinationRuleChanged := pushReq != nil && (pushReq.Full || 
HasConfigsOfKind(pushReq.ConfigsUpdated, kind.DestinationRule) ||
                len(pushReq.AddressesUpdated) > 0)
 
        if pushReq != nil {
-               subsetRuleCount := 0
+               destinationRuleCount := 0
                for cfg := range pushReq.ConfigsUpdated {
-                       if cfg.Kind == kind.SubsetRule {
-                               subsetRuleCount++
+                       if cfg.Kind == kind.DestinationRule {
+                               destinationRuleCount++
                        }
                }
-               if subsetRuleCount > 0 {
-                       log.Debugf("updateContext: detected %d SubsetRule 
config changes", subsetRuleCount)
+               if destinationRuleCount > 0 {
+                       log.Debugf("updateContext: detected %d DestinationRule 
config changes", destinationRuleCount)
                }
                if pushReq.Full {
-                       log.Debugf("updateContext: Full push requested, will 
re-initialize SubsetRule and ServiceRoute indexes")
+                       log.Debugf("updateContext: Full push requested, will 
re-initialize DestinationRule and ServiceRoute indexes")
                }
-               log.Debugf("updateContext: subsetRulesChanged=%v, 
serviceRoutesChanged=%v, pushReq.ConfigsUpdated size=%d, Full=%v",
-                       subsetRulesChanged, serviceRoutesChanged, 
len(pushReq.ConfigsUpdated), pushReq != nil && pushReq.Full)
+               log.Debugf("updateContext: destinationRuleChanged=%v, 
serviceRoutesChanged=%v, pushReq.ConfigsUpdated size=%d, Full=%v",
+                       destinationRuleChanged, serviceRoutesChanged, 
len(pushReq.ConfigsUpdated), pushReq != nil && pushReq.Full)
        }
 
        // Also check if the actual number of services has changed
@@ -636,12 +636,12 @@ func (ps *PushContext) updateContext(env *Environment, 
oldPushContext *PushConte
                ps.httpRouteIndex = oldPushContext.httpRouteIndex
        }
 
-       if subsetRulesChanged {
-               log.Debugf("updateContext: SubsetRules changed, re-initializing 
SubsetRule index")
-               ps.initSubsetRules(env)
+       if destinationRuleChanged {
+               log.Debugf("updateContext: DestinationRules changed, 
re-initializing DestinationRule index")
+               ps.initDestinationRules(env)
        } else {
-               log.Debugf("updateContext: SubsetRules unchanged, reusing old 
SubsetRule index")
-               ps.subsetRuleIndex = oldPushContext.subsetRuleIndex
+               log.Debugf("updateContext: DestinationRules unchanged, reusing 
old DestinationRule index")
+               ps.destinationRuleIndex = oldPushContext.destinationRuleIndex
        }
 
        authnPoliciesChanged := pushReq != nil && (pushReq.Full || 
HasConfigsOfKind(pushReq.ConfigsUpdated, kind.PeerAuthentication))
@@ -892,7 +892,7 @@ func sortConfigBySelectorAndCreationTime(configs 
[]config.Config) []config.Confi
        return configs
 }
 
-func (ps *PushContext) setSubsetRules(configs []config.Config) {
+func (ps *PushContext) setDestinationRules(configs []config.Config) {
        sortConfigBySelectorAndCreationTime(configs)
 
        namespaceLocalSubRules := make(map[string]*consolidatedSubRules)
@@ -927,13 +927,13 @@ func (ps *PushContext) setSubsetRules(configs 
[]config.Config) {
                        }
                        // Merge this destination rule with any public/private 
dest rules for same host in the same namespace
                        // If there are no duplicates, the dest rule will be 
added to the list
-                       
ps.mergeSubsetRule(namespaceLocalSubRules[configs[i].Namespace], configs[i], 
exportToSet)
+                       
ps.mergeDestinationRule(namespaceLocalSubRules[configs[i].Namespace], 
configs[i], exportToSet)
                }
 
                isPrivateOnly := false
                // No exportTo in destinationRule. Use the global default
                // We only honor . and *
-               if exportToSet.IsEmpty() && 
ps.exportToDefaults.subsetRule.Contains(visibility.Private) {
+               if exportToSet.IsEmpty() && 
ps.exportToDefaults.destinationRule.Contains(visibility.Private) {
                        isPrivateOnly = true
                } else if exportToSet.Len() == 1 && 
(exportToSet.Contains(visibility.Private) || 
exportToSet.Contains(visibility.Instance(configs[i].Namespace))) {
                        isPrivateOnly = true
@@ -943,18 +943,18 @@ func (ps *PushContext) setSubsetRules(configs 
[]config.Config) {
                        if _, exist := 
exportedDestRulesByNamespace[configs[i].Namespace]; !exist {
                                
exportedDestRulesByNamespace[configs[i].Namespace] = newConsolidatedDestRules()
                        }
-                       
ps.mergeSubsetRule(exportedDestRulesByNamespace[configs[i].Namespace], 
configs[i], exportToSet)
+                       
ps.mergeDestinationRule(exportedDestRulesByNamespace[configs[i].Namespace], 
configs[i], exportToSet)
                } else if configs[i].Namespace == ps.Mesh.RootNamespace {
-                       ps.mergeSubsetRule(rootNamespaceLocalDestRules, 
configs[i], exportToSet)
+                       ps.mergeDestinationRule(rootNamespaceLocalDestRules, 
configs[i], exportToSet)
                }
        }
 
-       ps.subsetRuleIndex.namespaceLocal = namespaceLocalSubRules
-       ps.subsetRuleIndex.exportedByNamespace = exportedDestRulesByNamespace
-       ps.subsetRuleIndex.rootNamespaceLocal = rootNamespaceLocalDestRules
+       ps.destinationRuleIndex.namespaceLocal = namespaceLocalSubRules
+       ps.destinationRuleIndex.exportedByNamespace = 
exportedDestRulesByNamespace
+       ps.destinationRuleIndex.rootNamespaceLocal = rootNamespaceLocalDestRules
 
        // Log indexing results
-       log.Debugf("setSubsetRules: indexed %d namespaces with local rules", 
len(namespaceLocalSubRules))
+       log.Debugf("setDestinationRules: indexed %d namespaces with local 
rules", len(namespaceLocalSubRules))
        for ns, rules := range namespaceLocalSubRules {
                totalRules := 0
                for hostname, ruleList := range rules.specificSubRules {
@@ -967,26 +967,26 @@ func (ps *PushContext) setSubsetRules(configs 
[]config.Config) {
                                        if hasTLS {
                                                tlsMode = 
dr.TrafficPolicy.Tls.Mode.String()
                                        }
-                                       log.Debugf("setSubsetRules: namespace 
%s, hostname %s: DestinationRule has %d subsets, TLS mode: %s",
+                                       log.Debugf("setDestinationRules: 
namespace %s, hostname %s: DestinationRule has %d subsets, TLS mode: %s",
                                                ns, hostname, len(dr.Subsets), 
tlsMode)
                                }
                        }
                }
-               log.Debugf("setSubsetRules: namespace %s has %d 
DestinationRules with %d specific hostnames", ns, totalRules, 
len(rules.specificSubRules))
+               log.Debugf("setDestinationRules: namespace %s has %d 
DestinationRules with %d specific hostnames", ns, totalRules, 
len(rules.specificSubRules))
        }
-       log.Debugf("setSubsetRules: indexed %d namespaces with exported rules", 
len(exportedDestRulesByNamespace))
+       log.Debugf("setDestinationRules: indexed %d namespaces with exported 
rules", len(exportedDestRulesByNamespace))
        if rootNamespaceLocalDestRules != nil {
                totalRootRules := 0
                for _, ruleList := range 
rootNamespaceLocalDestRules.specificSubRules {
                        totalRootRules += len(ruleList)
                }
-               log.Debugf("setSubsetRules: root namespace has %d 
DestinationRules with %d specific hostnames", totalRootRules, 
len(rootNamespaceLocalDestRules.specificSubRules))
+               log.Debugf("setDestinationRules: root namespace has %d 
DestinationRules with %d specific hostnames", totalRootRules, 
len(rootNamespaceLocalDestRules.specificSubRules))
        }
 }
 
-func (ps *PushContext) initSubsetRules(env *Environment) {
-       configs := env.List(gvk.SubsetRule, NamespaceAll)
-       log.Debugf("initSubsetRules: found %d SubsetRule configs", len(configs))
+func (ps *PushContext) initDestinationRules(env *Environment) {
+       configs := env.List(gvk.DestinationRule, NamespaceAll)
+       log.Debugf("initDestinationRules: found %d DestinationRule configs", 
len(configs))
 
        // values returned from ConfigStore.List are immutable.
        // Therefore, we make a copy
@@ -998,12 +998,12 @@ func (ps *PushContext) initSubsetRules(env *Environment) {
                        if dr.TrafficPolicy != nil && dr.TrafficPolicy.Tls != 
nil {
                                tlsMode = dr.TrafficPolicy.Tls.Mode.String()
                        }
-                       log.Debugf("initSubsetRules: SubsetRule %s/%s for host 
%s with %d subsets, TLS mode: %s",
+                       log.Debugf("initDestinationRules: DestinationRule %s/%s 
for host %s with %d subsets, TLS mode: %s",
                                configs[i].Namespace, configs[i].Name, dr.Host, 
len(dr.Subsets), tlsMode)
                }
        }
 
-       ps.setSubsetRules(subRules)
+       ps.setDestinationRules(subRules)
 }
 
 func (ps *PushContext) initServiceAccounts(env *Environment, services 
[]*Service) {
@@ -1049,12 +1049,12 @@ func (ps *PushContext) ServiceRouteForHost(hostname 
host.Name) *networking.Virtu
        return nil
 }
 
-// DestinationRuleForService returns the first DestinationRule (SubsetRule) 
applicable to the service hostname/namespace.
+// DestinationRuleForService returns the first DestinationRule applicable to 
the service hostname/namespace.
 func (ps *PushContext) DestinationRuleForService(namespace string, hostname 
host.Name) *networking.DestinationRule {
        log.Debugf("DestinationRuleForService: looking for DestinationRule for 
%s/%s", namespace, hostname)
 
        // Check namespace-local rules first
-       if nsRules := ps.subsetRuleIndex.namespaceLocal[namespace]; nsRules != 
nil {
+       if nsRules := ps.destinationRuleIndex.namespaceLocal[namespace]; 
nsRules != nil {
                log.Debugf("DestinationRuleForService: checking namespace-local 
rules for %s (found %d specific rules)", namespace, 
len(nsRules.specificSubRules))
                if dr := firstDestinationRule(nsRules, hostname); dr != nil {
                        hasTLS := dr.TrafficPolicy != nil && 
dr.TrafficPolicy.Tls != nil
@@ -1071,8 +1071,8 @@ func (ps *PushContext) 
DestinationRuleForService(namespace string, hostname host
        }
 
        // Check exported rules
-       log.Debugf("DestinationRuleForService: checking exported rules (found 
%d exported namespaces)", len(ps.subsetRuleIndex.exportedByNamespace))
-       for ns, exported := range ps.subsetRuleIndex.exportedByNamespace {
+       log.Debugf("DestinationRuleForService: checking exported rules (found 
%d exported namespaces)", len(ps.destinationRuleIndex.exportedByNamespace))
+       for ns, exported := range ps.destinationRuleIndex.exportedByNamespace {
                if dr := firstDestinationRule(exported, hostname); dr != nil {
                        hasTLS := dr.TrafficPolicy != nil && 
dr.TrafficPolicy.Tls != nil
                        tlsMode := "none"
@@ -1086,7 +1086,7 @@ func (ps *PushContext) 
DestinationRuleForService(namespace string, hostname host
        }
 
        // Finally, check root namespace scoped rules
-       if rootRules := ps.subsetRuleIndex.rootNamespaceLocal; rootRules != nil 
{
+       if rootRules := ps.destinationRuleIndex.rootNamespaceLocal; rootRules 
!= nil {
                log.Debugf("DestinationRuleForService: checking root namespace 
rules (found %d specific rules)", len(rootRules.specificSubRules))
                if dr := firstDestinationRule(rootRules, hostname); dr != nil {
                        hasTLS := dr.TrafficPolicy != nil && 
dr.TrafficPolicy.Tls != nil
@@ -1129,7 +1129,7 @@ func firstDestinationRule(csr *consolidatedSubRules, 
hostname host.Name) *networ
        if rules := csr.specificSubRules[hostname]; len(rules) > 0 {
                log.Infof("firstDestinationRule: found %d rules for hostname 
%s", len(rules), hostname)
                // The first rule should contain the merged result if merge was 
successful.
-               // However, if merge failed (e.g., 
EnableEnhancedSubsetRuleMerge is disabled),
+               // However, if merge failed (e.g., 
EnableEnhancedDestinationRuleMerge is disabled),
                // we need to check all rules and prefer the one with TLS 
configuration.
                // we return the one that has TLS if available, or the first 
one otherwise.
                var bestRule *networking.DestinationRule
diff --git a/dubbod/planet/pkg/model/service.go 
b/dubbod/planet/pkg/model/service.go
index 3a47dc6c..27e25a25 100644
--- a/dubbod/planet/pkg/model/service.go
+++ b/dubbod/planet/pkg/model/service.go
@@ -17,8 +17,6 @@
 package model
 
 import (
-       "istio.io/api/annotation"
-       corev1 "k8s.io/api/core/v1"
        "strconv"
        "strings"
        "sync"
@@ -56,14 +54,6 @@ const (
        Terminating HealthStatus = 4
 )
 
-type TrafficDistribution int
-
-const (
-       TrafficDistributionAny TrafficDistribution = iota
-       TrafficDistributionPreferSameZone
-       TrafficDistributionPreferSameNode
-)
-
 type TrafficDirection string
 
 const (
@@ -154,10 +144,6 @@ type K8sAttributes struct {
        // spec.InternalTrafficPolicy == Local
        NodeLocal bool
 
-       // TrafficDistribution determines the service-level traffic 
distribution.
-       // This may be overridden by locality load balancing settings.
-       TrafficDistribution TrafficDistribution
-
        // ObjectName is the object name of the underlying object. This may 
differ from the Service.Attributes.Name for legacy semantics.
        ObjectName string
 
@@ -515,31 +501,6 @@ func (m *AddressMap) DeepCopy() *AddressMap {
        }
 }
 
-func GetTrafficDistribution(specValue *string, annotations map[string]string) 
TrafficDistribution {
-       if specValue != nil {
-               switch *specValue {
-               case corev1.ServiceTrafficDistributionPreferSameZone, 
corev1.ServiceTrafficDistributionPreferClose:
-                       return TrafficDistributionPreferSameZone
-               case corev1.ServiceTrafficDistributionPreferSameNode:
-                       return TrafficDistributionPreferSameNode
-               }
-       }
-       // The TrafficDistribution field is quite new, so we allow a legacy 
annotation option as well
-       // This also has some custom types
-       trafficDistributionAnnotationValue := 
strings.ToLower(annotations[annotation.NetworkingTrafficDistribution.Name])
-       switch trafficDistributionAnnotationValue {
-       case strings.ToLower(corev1.ServiceTrafficDistributionPreferClose), 
strings.ToLower(corev1.ServiceTrafficDistributionPreferSameZone):
-               return TrafficDistributionPreferSameZone
-       case strings.ToLower(corev1.ServiceTrafficDistributionPreferSameNode):
-               return TrafficDistributionPreferSameNode
-       default:
-               if trafficDistributionAnnotationValue != "" {
-                       log.Warnf("Unknown traffic distribution annotation, 
defaulting to any")
-               }
-               return TrafficDistributionAny
-       }
-}
-
 func BuildSubsetKey(direction TrafficDirection, subsetName string, hostname 
host.Name, port int) string {
        return string(direction) + "|" + strconv.Itoa(port) + "|" + subsetName 
+ "|" + string(hostname)
 }
diff --git a/dubbod/planet/pkg/networking/grpcgen/cds.go 
b/dubbod/planet/pkg/networking/grpcgen/cds.go
index 78a4a90c..cf90f252 100644
--- a/dubbod/planet/pkg/networking/grpcgen/cds.go
+++ b/dubbod/planet/pkg/networking/grpcgen/cds.go
@@ -239,9 +239,9 @@ func (b *clusterBuilder) 
applyDestinationRule(defaultCluster *cluster.Cluster) (
 
        // Apply TLS to default cluster if it exists and doesn't have 
TransportSocket yet
        // This ensures that default cluster gets TLS from the top-level 
TrafficPolicy in DestinationRule
-       // When SubsetRule sets ISTIO_MUTUAL, inbound listener enforces STRICT 
mTLS, so outbound must also use TLS
+       // When DestinationRule sets ISTIO_MUTUAL, inbound listener enforces 
STRICT mTLS, so outbound must also use TLS
        // NOTE: We re-check hasTLS here because firstDestinationRule might 
have returned a different rule
-       // than the one checked in build(), especially when multiple 
SubsetRules exist and merge failed
+       // than the one checked in build(), especially when multiple 
DestinationRules exist and merge failed
        if defaultCluster != nil && defaultCluster.TransportSocket == nil {
                // Re-check TLS in case DestinationRule was found here but not 
in build()
                recheckTLS := dr != nil && dr.TrafficPolicy != nil && 
dr.TrafficPolicy.Tls != nil
diff --git a/dubbod/planet/pkg/serviceregistry/kube/controller/controller.go 
b/dubbod/planet/pkg/serviceregistry/kube/controller/controller.go
index a1dbf0e9..6e393271 100644
--- a/dubbod/planet/pkg/serviceregistry/kube/controller/controller.go
+++ b/dubbod/planet/pkg/serviceregistry/kube/controller/controller.go
@@ -43,7 +43,6 @@ import (
        "github.com/apache/dubbo-kubernetes/pkg/slices"
        "github.com/hashicorp/go-multierror"
        "go.uber.org/atomic"
-       "istio.io/api/label"
        v1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        klabels "k8s.io/apimachinery/pkg/labels"
@@ -550,7 +549,7 @@ func (c *Controller) servicesForNamespacedName(name 
types.NamespacedName) []*mod
 
 func (c *Controller) Network(endpointIP string, labels labels.Instance) 
network.ID {
        // 1. check the pod/workloadEntry label
-       if nw := labels[label.TopologyNetwork.Name]; nw != "" {
+       if nw := labels["topology.dubbo.apache.org/network"]; nw != "" {
                return network.ID(nw)
        }
        // 2. check the system namespace labels
diff --git a/dubbod/planet/pkg/serviceregistry/kube/controller/endpointslice.go 
b/dubbod/planet/pkg/serviceregistry/kube/controller/endpointslice.go
index dc616d46..65102397 100644
--- a/dubbod/planet/pkg/serviceregistry/kube/controller/endpointslice.go
+++ b/dubbod/planet/pkg/serviceregistry/kube/controller/endpointslice.go
@@ -18,18 +18,15 @@ package controller
 
 import (
        "fmt"
-       "strings"
        "sync"
 
        "github.com/apache/dubbo-kubernetes/dubbod/planet/pkg/model"
        "github.com/apache/dubbo-kubernetes/pkg/config"
        "github.com/apache/dubbo-kubernetes/pkg/config/host"
        "github.com/apache/dubbo-kubernetes/pkg/config/schema/kind"
-       "github.com/apache/dubbo-kubernetes/pkg/config/visibility"
        "github.com/apache/dubbo-kubernetes/pkg/kube/kclient"
        "github.com/apache/dubbo-kubernetes/pkg/util/sets"
        "github.com/hashicorp/go-multierror"
-       "istio.io/api/annotation"
        corev1 "k8s.io/api/core/v1"
        v1 "k8s.io/api/discovery/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -524,15 +521,7 @@ func getServiceNamespacedName(slice *v1.EndpointSlice) 
types.NamespacedName {
 }
 
 func serviceNeedsPush(svc *corev1.Service) bool {
-       if svc.Annotations[annotation.NetworkingExportTo.Name] != "" {
-               namespaces := 
strings.Split(svc.Annotations[annotation.NetworkingExportTo.Name], ",")
-               for _, ns := range namespaces {
-                       ns = strings.TrimSpace(ns)
-                       if ns == string(visibility.None) {
-                               return false
-                       }
-               }
-       }
+       // In proxyless mesh, all services need to be pushed
        return true
 }
 
diff --git a/dubbod/planet/pkg/serviceregistry/kube/controller/pod.go 
b/dubbod/planet/pkg/serviceregistry/kube/controller/pod.go
index e956d514..799d0c1d 100644
--- a/dubbod/planet/pkg/serviceregistry/kube/controller/pod.go
+++ b/dubbod/planet/pkg/serviceregistry/kube/controller/pod.go
@@ -24,7 +24,6 @@ import (
        "github.com/apache/dubbo-kubernetes/pkg/kube/kclient"
        "github.com/apache/dubbo-kubernetes/pkg/maps"
        "github.com/apache/dubbo-kubernetes/pkg/util/sets"
-       "istio.io/api/annotation"
        v1 "k8s.io/api/core/v1"
        "k8s.io/apimachinery/pkg/types"
 )
@@ -193,12 +192,9 @@ func (pc *PodCache) deleteIP(ip string, podKey 
types.NamespacedName) bool {
 }
 
 func (pc *PodCache) labelFilter(old, cur *v1.Pod) bool {
-       // If labels/annotations updated, trigger proxy push
-       labelsChanged := !maps.Equal(old.Labels, cur.Labels)
-       // Annotations are only used in endpoints in one case, so just compare 
that one
-       relevantAnnotationsChanged := 
old.Annotations[annotation.AmbientRedirection.Name] != 
cur.Annotations[annotation.AmbientRedirection.Name]
-       changed := labelsChanged || relevantAnnotationsChanged
-       return changed
+       // If labels updated, trigger proxy push
+       // In proxyless mesh, we don't need to check ambient redirection 
annotations
+       return !maps.Equal(old.Labels, cur.Labels)
 }
 
 func (pc *PodCache) proxyUpdates(pod *v1.Pod, isPodUpdate bool) {
diff --git a/dubbod/planet/pkg/serviceregistry/kube/conversion.go 
b/dubbod/planet/pkg/serviceregistry/kube/conversion.go
index 86ede643..1ab025fd 100644
--- a/dubbod/planet/pkg/serviceregistry/kube/conversion.go
+++ b/dubbod/planet/pkg/serviceregistry/kube/conversion.go
@@ -17,8 +17,6 @@
 package kube
 
 import (
-       "strings"
-
        meshv1alpha1 "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
        "github.com/apache/dubbo-kubernetes/dubbod/planet/pkg/model"
        
"github.com/apache/dubbo-kubernetes/dubbod/planet/pkg/serviceregistry/provider"
@@ -26,10 +24,7 @@ import (
        "github.com/apache/dubbo-kubernetes/pkg/config/constants"
        "github.com/apache/dubbo-kubernetes/pkg/config/host"
        "github.com/apache/dubbo-kubernetes/pkg/config/kube"
-       "github.com/apache/dubbo-kubernetes/pkg/config/visibility"
        "github.com/apache/dubbo-kubernetes/pkg/spiffe"
-       "github.com/apache/dubbo-kubernetes/pkg/util/sets"
-       "istio.io/api/annotation"
        corev1 "k8s.io/api/core/v1"
 )
 
@@ -41,17 +36,12 @@ func ConvertService(svc corev1.Service, domainSuffix 
string, clusterID cluster.I
        addrs := []string{constants.UnspecifiedIP}
        resolution := model.ClientSideLB
        externalName := ""
-       nodeLocal := false
 
        if svc.Spec.Type == corev1.ServiceTypeExternalName && 
svc.Spec.ExternalName != "" {
                externalName = svc.Spec.ExternalName
                resolution = model.Alias
        }
 
-       if svc.Spec.InternalTrafficPolicy != nil && 
*svc.Spec.InternalTrafficPolicy == corev1.ServiceInternalTrafficPolicyLocal {
-               nodeLocal = true
-       }
-
        if svc.Spec.ClusterIP == corev1.ClusterIPNone { // headless services 
should not be load balanced
                resolution = model.Passthrough
        } else if svc.Spec.ClusterIP != "" {
@@ -65,24 +55,6 @@ func ConvertService(svc corev1.Service, domainSuffix string, 
clusterID cluster.I
        for _, port := range svc.Spec.Ports {
                ports = append(ports, convertPort(port))
        }
-       var exportTo sets.Set[visibility.Instance]
-       serviceaccounts := make([]string, 0)
-       if svc.Annotations[annotation.AlphaCanonicalServiceAccounts.Name] != "" 
{
-               serviceaccounts = append(serviceaccounts, 
strings.Split(svc.Annotations[annotation.AlphaCanonicalServiceAccounts.Name], 
",")...)
-       }
-       if svc.Annotations[annotation.AlphaKubernetesServiceAccounts.Name] != 
"" {
-               for _, ksa := range 
strings.Split(svc.Annotations[annotation.AlphaKubernetesServiceAccounts.Name], 
",") {
-                       serviceaccounts = append(serviceaccounts, 
kubeToDubboServiceAccount(ksa, svc.Namespace, mesh))
-               }
-       }
-       if svc.Annotations[annotation.NetworkingExportTo.Name] != "" {
-               namespaces := 
strings.Split(svc.Annotations[annotation.NetworkingExportTo.Name], ",")
-               exportTo = 
sets.NewWithLength[visibility.Instance](len(namespaces))
-               for _, ns := range namespaces {
-                       ns = strings.TrimSpace(ns)
-                       exportTo.Insert(visibility.Instance(ns))
-               }
-       }
 
        dubboService := &model.Service{
                Hostname: ServiceHostname(svc.Name, svc.Namespace, 
domainSuffix),
@@ -94,65 +66,19 @@ func ConvertService(svc corev1.Service, domainSuffix 
string, clusterID cluster.I
                Ports:           ports,
                DefaultAddress:  addrs[0],
                Resolution:      resolution,
-               ServiceAccounts: serviceaccounts,
                ResourceVersion: svc.ResourceVersion,
                Attributes: model.ServiceAttributes{
                        ServiceRegistry: provider.Kubernetes,
                        Name:            svc.Name,
                        Namespace:       svc.Namespace,
                        Labels:          svc.Labels,
-                       ExportTo:        exportTo,
                        LabelSelectors:  svc.Spec.Selector,
                },
        }
 
-       switch svc.Spec.Type {
-       case corev1.ServiceTypeNodePort:
-               if _, ok := 
svc.Annotations[annotation.TrafficNodeSelector.Name]; !ok {
-                       break
-               }
-               // store the service port to node port mappings
-               portMap := make(map[uint32]uint32)
-               for _, p := range svc.Spec.Ports {
-                       portMap[uint32(p.Port)] = uint32(p.NodePort)
-               }
-               dubboService.Attributes.ClusterExternalPorts = 
map[cluster.ID]map[uint32]uint32{clusterID: portMap}
-               // address mappings will be done elsewhere
-       case corev1.ServiceTypeLoadBalancer:
-               if len(svc.Status.LoadBalancer.Ingress) > 0 {
-                       var lbAddrs []string
-                       for _, ingress := range svc.Status.LoadBalancer.Ingress 
{
-                               if len(ingress.IP) > 0 {
-                                       lbAddrs = append(lbAddrs, ingress.IP)
-                               } else if len(ingress.Hostname) > 0 {
-                                       // DO NOT resolve the DNS here. In 
environments like AWS, the ELB hostname
-                                       // does not have a repeatable DNS 
address and IPs resolved at an earlier point
-                                       // in time may not work. So, when we 
get just hostnames instead of IPs, we need
-                                       // to smartly switch from EDS to 
strict_dns rather than doing the naive thing of
-                                       // resolving the DNS name and hoping 
the resolution is one-time task.
-                                       lbAddrs = append(lbAddrs, 
ingress.Hostname)
-                               }
-                       }
-                       if len(lbAddrs) > 0 {
-                               if 
dubboService.Attributes.ClusterExternalAddresses == nil {
-                                       
dubboService.Attributes.ClusterExternalAddresses = &model.AddressMap{}
-                               }
-                               
dubboService.Attributes.ClusterExternalAddresses.SetAddressesFor(clusterID, 
lbAddrs)
-                       }
-               }
-       }
-
        dubboService.Attributes.Type = string(svc.Spec.Type)
        dubboService.Attributes.ExternalName = externalName
-       dubboService.Attributes.TrafficDistribution = 
model.GetTrafficDistribution(svc.Spec.TrafficDistribution, svc.Annotations)
-       dubboService.Attributes.NodeLocal = nodeLocal
        dubboService.Attributes.PublishNotReadyAddresses = 
svc.Spec.PublishNotReadyAddresses
-       if len(svc.Spec.ExternalIPs) > 0 {
-               if dubboService.Attributes.ClusterExternalAddresses == nil {
-                       dubboService.Attributes.ClusterExternalAddresses = 
&model.AddressMap{}
-               }
-               
dubboService.Attributes.ClusterExternalAddresses.AddAddressesFor(clusterID, 
svc.Spec.ExternalIPs)
-       }
        return dubboService
 }
 
@@ -164,10 +90,6 @@ func convertPort(port corev1.ServicePort) *model.Port {
        }
 }
 
-func kubeToDubboServiceAccount(saname string, ns string, mesh 
*meshv1alpha1.MeshGlobalConfig) string {
-       return spiffe.MustGenSpiffeURI(mesh, ns, saname)
-}
-
 func SecureNamingSAN(pod *corev1.Pod, mesh *meshv1alpha1.MeshGlobalConfig) 
string {
        return spiffe.MustGenSpiffeURI(mesh, pod.Namespace, 
pod.Spec.ServiceAccountName)
 }
diff --git a/dubbod/planet/pkg/serviceregistry/util/label/label.go 
b/dubbod/planet/pkg/serviceregistry/util/label/label.go
index d0b065ae..7b2db81e 100644
--- a/dubbod/planet/pkg/serviceregistry/util/label/label.go
+++ b/dubbod/planet/pkg/serviceregistry/util/label/label.go
@@ -17,61 +17,31 @@
 package label
 
 import (
-       "strings"
-
        "github.com/apache/dubbo-kubernetes/pkg/cluster"
        "github.com/apache/dubbo-kubernetes/pkg/config/labels"
        "github.com/apache/dubbo-kubernetes/pkg/network"
-       "istio.io/api/label"
 )
 
 const (
-       LabelHostname = "kubernetes.io/hostname"
-
-       LabelTopologyZone    = "topology.kubernetes.io/zone"
-       LabelTopologySubzone = "topology.dubbo.apache.org/subzone"
-       LabelTopologyRegion  = "topology.kubernetes.io/region"
+       LabelTopologyCluster = "topology.dubbo.apache.org/cluster"
+       LabelTopologyNetwork = "topology.dubbo.apache.org/network"
 )
 
 func AugmentLabels(in labels.Instance, clusterID cluster.ID, locality, k8sNode 
string, networkID network.ID) labels.Instance {
        // Copy the original labels to a new map.
-       out := make(labels.Instance, len(in)+6)
+       out := make(labels.Instance, len(in)+2)
        for k, v := range in {
                out[k] = v
        }
 
-       region, zone, subzone := SplitLocalityLabel(locality)
-       if len(region) > 0 {
-               out[LabelTopologyRegion] = region
-       }
-       if len(zone) > 0 {
-               out[LabelTopologyZone] = zone
-       }
-       if len(subzone) > 0 {
-               out[label.TopologySubzone.Name] = subzone
-       }
+       // In proxyless mesh, locality is not used, so we skip 
region/zone/subzone labels
        if len(clusterID) > 0 {
-               out[label.TopologyCluster.Name] = clusterID.String()
-       }
-       if len(k8sNode) > 0 {
-               out[LabelHostname] = k8sNode
+               out[LabelTopologyCluster] = clusterID.String()
        }
        // In c.Network(), we already set the network label in priority order 
pod labels > namespace label
        // We won't let proxy.Metadata.Network override the above.
-       if len(networkID) > 0 && out[label.TopologyNetwork.Name] == "" {
-               out[label.TopologyNetwork.Name] = networkID.String()
+       if len(networkID) > 0 && out[LabelTopologyNetwork] == "" {
+               out[LabelTopologyNetwork] = networkID.String()
        }
        return out
 }
-
-func SplitLocalityLabel(locality string) (region, zone, subzone string) {
-       items := strings.Split(locality, "/")
-       switch len(items) {
-       case 1:
-               return items[0], "", ""
-       case 2:
-               return items[0], items[1], ""
-       default:
-               return items[0], items[1], items[2]
-       }
-}
diff --git a/dubbod/planet/pkg/xds/cds.go b/dubbod/planet/pkg/xds/cds.go
index 7bf7987a..733f7319 100644
--- a/dubbod/planet/pkg/xds/cds.go
+++ b/dubbod/planet/pkg/xds/cds.go
@@ -34,11 +34,11 @@ func cdsNeedsPush(req *model.PushRequest, proxy 
*model.Proxy) (*model.PushReques
        }
 
        // with TLS configuration (ISTIO_MUTUAL), CDS must be pushed to update 
cluster TransportSocket.
-       // Even if req.Full is false, we need to check if SubsetRule was 
updated, as it affects cluster TLS config.
+       // Even if req.Full is false, we need to check if DestinationRule was 
updated, as it affects cluster TLS config.
        if req != nil && req.ConfigsUpdated != nil {
-               // Check if SubsetRule was updated - this requires CDS push to 
update cluster TransportSocket
-               if model.HasConfigsOfKind(req.ConfigsUpdated, kind.SubsetRule) {
-                       log.Debugf("cdsNeedsPush: SubsetRule updated, CDS push 
required to update cluster TLS config")
+               // Check if DestinationRule was updated - this requires CDS 
push to update cluster TransportSocket
+               if model.HasConfigsOfKind(req.ConfigsUpdated, 
kind.DestinationRule) {
+                       log.Debugf("cdsNeedsPush: DestinationRule updated, CDS 
push required to update cluster TLS config")
                        return req, true
                }
        }
diff --git a/go.mod b/go.mod
index 72963c4b..719cf87c 100644
--- a/go.mod
+++ b/go.mod
@@ -158,6 +158,7 @@ require (
        github.com/gobwas/glob v0.2.3 // indirect
        github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
        github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // 
indirect
+       github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a // 
indirect
        github.com/google/btree v1.1.3 // indirect
        github.com/google/gnostic-models v0.7.0 // indirect
        github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a // indirect
diff --git a/go.sum b/go.sum
index c7a2c11a..208bf724 100644
--- a/go.sum
+++ b/go.sum
@@ -343,6 +343,8 @@ github.com/golang/protobuf v1.4.0/go.mod 
h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
 github.com/golang/protobuf v1.4.1/go.mod 
h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 github.com/golang/protobuf v1.5.4 
h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 github.com/golang/protobuf v1.5.4/go.mod 
h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a 
h1:l7A0loSszR5zHd/qK53ZIHMO8b3bBSmENnQ6eKnUT0A=
+github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a/go.mod 
h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
 github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
 github.com/google/btree v1.1.3/go.mod 
h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
 github.com/google/generative-ai-go v0.15.1 
h1:n8aQUpvhPOlGVuM2DRkJ2jvx04zpp42B778AROJa+pQ=
diff --git a/manifests/charts/base/files/crd-all.yaml 
b/manifests/charts/base/files/crd-all.yaml
index 96333392..91b32e55 100644
--- a/manifests/charts/base/files/crd-all.yaml
+++ b/manifests/charts/base/files/crd-all.yaml
@@ -24,19 +24,19 @@ metadata:
     chart: dubbo
     heritage: Tiller
     release: dubbo
-  name: subsetrules.networking.dubbo.apache.org
+  name: destinationrules.networking.dubbo.apache.org
 spec:
   group: networking.dubbo.apache.org
   names:
     categories:
       - dubbo
       - networking
-    kind: SubsetRule
-    listKind: SubsetRuleList
-    plural: subsetrules
+    kind: DestinationRule
+    listKind: DestinationRuleList
+    plural: destinationrules
     shortNames:
-      - ssr
-    singular: subsetrules
+      - dr
+    singular: destinationrule
   scope: Namespaced
   versions:
     - additionalPrinterColumns:
@@ -95,7 +95,7 @@ spec:
                                   - DISABLE
                                   - SIMPLE
                                   - MUTUAL
-                                  - ISTIO_MUTUAL
+                                  - DUBBO_MUTUAL
                                 type: string
                             type: object
                         type: object
@@ -114,12 +114,12 @@ spec:
                           description: |-
                             Indicates whether connections to this port should 
be secured using TLS.
                             
-                            Valid Options: DISABLE, SIMPLE, MUTUAL, 
ISTIO_MUTUAL
+                            Valid Options: DISABLE, SIMPLE, MUTUAL, 
DUBBO_MUTUAL
                           enum:
                             - DISABLE
                             - SIMPLE
                             - MUTUAL
-                            - ISTIO_MUTUAL
+                            - DUBBO_MUTUAL
                           type: string
                       type: object
                   type: object
diff --git a/pkg/adsc/adsc.go b/pkg/adsc/adsc.go
index f5858216..efb53294 100644
--- a/pkg/adsc/adsc.go
+++ b/pkg/adsc/adsc.go
@@ -33,7 +33,6 @@ import (
        "github.com/apache/dubbo-kubernetes/dubbod/planet/pkg/networking/util"
        v3 "github.com/apache/dubbo-kubernetes/dubbod/planet/pkg/xds/v3"
        "github.com/apache/dubbo-kubernetes/pkg/backoff"
-       "github.com/apache/dubbo-kubernetes/pkg/config"
        "github.com/apache/dubbo-kubernetes/pkg/config/schema/collections"
        "github.com/apache/dubbo-kubernetes/pkg/config/schema/gvk"
        "github.com/apache/dubbo-kubernetes/pkg/security"
@@ -49,9 +48,7 @@ import (
        "google.golang.org/grpc/credentials"
        "google.golang.org/grpc/credentials/insecure"
        "google.golang.org/protobuf/proto"
-       anypb "google.golang.org/protobuf/types/known/anypb"
        pstruct "google.golang.org/protobuf/types/known/structpb"
-       mcp "istio.io/api/mcp/v1alpha1"
 
        dubbolog "github.com/apache/dubbo-kubernetes/pkg/log"
 )
@@ -91,7 +88,7 @@ type Config struct {
        Revision string
        // Meta includes additional metadata for the node
        Meta *pstruct.Struct
-       // BackoffPolicy determines the reconnect policy. Based on MCP client.
+       // BackoffPolicy determines the reconnect policy.
        BackoffPolicy backoff.BackOff
 }
 
@@ -348,26 +345,10 @@ func (a *ADSC) WaitClear() {
        }
 }
 
-// HasSynced returns true if MCP configs have synced
+// HasSynced returns true if configs have synced
+// MCP support removed - it's a legacy protocol replaced by APIGenerator
 func (a *ADSC) HasSynced() bool {
-       if a.cfg == nil || len(a.cfg.InitialDiscoveryRequests) == 0 {
-               return true
-       }
-
-       a.mutex.RLock()
-       defer a.mutex.RUnlock()
-
-       for _, req := range a.cfg.InitialDiscoveryRequests {
-               _, isMCP := convertTypeURLToMCPGVK(req.TypeUrl)
-               if !isMCP {
-                       continue
-               }
-
-               if _, ok := a.sync[req.TypeUrl]; !ok {
-                       return false
-               }
-       }
-
+       // MCP was replaced by APIGenerator in Istio, not needed for proxyless 
mesh
        return true
 }
 
@@ -423,41 +404,6 @@ func (a *ADSC) ack(msg *discovery.DiscoveryResponse) {
        })
 }
 
-func (a *ADSC) mcpToPlanet(m *mcp.Resource) (*config.Config, error) {
-       if m == nil || m.Metadata == nil {
-               return &config.Config{}, nil
-       }
-       c := &config.Config{
-               Meta: config.Meta{
-                       ResourceVersion: m.Metadata.Version,
-                       Labels:          m.Metadata.Labels,
-                       Annotations:     m.Metadata.Annotations,
-               },
-       }
-
-       if !config.ObjectInRevision(c, a.cfg.Revision) { // In case upstream 
does not support rev in node meta.
-               return nil, nil
-       }
-
-       if c.Meta.Annotations == nil {
-               c.Meta.Annotations = make(map[string]string)
-       }
-       nsn := strings.Split(m.Metadata.Name, "/")
-       if len(nsn) != 2 {
-               return nil, fmt.Errorf("invalid name %s", m.Metadata.Name)
-       }
-       c.Namespace = nsn[0]
-       c.Name = nsn[1]
-       var err error
-       c.CreationTimestamp = m.Metadata.CreateTime.AsTime()
-
-       pb, err := m.Body.UnmarshalNew()
-       if err != nil {
-               return nil, err
-       }
-       c.Spec = pb
-       return c, nil
-}
 
 func (a *ADSC) handleRecv() {
        // We connected, so reset the backoff
@@ -487,7 +433,7 @@ func (a *ADSC) handleRecv() {
                }
 
                // Group-value-kind - used for high level api generator.
-               resourceGvk, isMCP := convertTypeURLToMCPGVK(msg.TypeUrl)
+               // MCP support removed - it's a legacy protocol replaced by 
APIGenerator
 
                // TODO WithLabels
                if a.cfg.ResponseHandler != nil {
@@ -546,9 +492,7 @@ func (a *ADSC) handleRecv() {
                        }
                        a.handleRDS(routes)
                default:
-                       if isMCP {
-                               a.handleMCP(resourceGvk, msg.Resources)
-                       }
+                       // MCP support removed - it's a legacy protocol 
replaced by APIGenerator
                }
 
                // If we got no resource - still save to the store with empty 
name/namespace, to notify sync
@@ -557,11 +501,6 @@ func (a *ADSC) handleRecv() {
                // TODO: add hook to inject nacks
 
                a.mutex.Lock()
-               if isMCP {
-                       if _, exist := a.sync[resourceGvk.String()]; !exist {
-                               a.sync[resourceGvk.String()] = time.Now()
-                       }
-               }
                a.Received[msg.TypeUrl] = msg
                a.ack(msg)
                a.mutex.Unlock()
@@ -573,62 +512,6 @@ func (a *ADSC) handleRecv() {
        }
 }
 
-func (a *ADSC) handleMCP(groupVersionKind config.GroupVersionKind, resources 
[]*anypb.Any) {
-       // Generic - fill up the store
-       if a.Store == nil {
-               return
-       }
-
-       existingConfigs := a.Store.List(groupVersionKind, "")
-
-       received := make(map[string]*config.Config)
-       for _, rsc := range resources {
-               m := &mcp.Resource{}
-               err := rsc.UnmarshalTo(m)
-               if err != nil {
-                       log.Errorf("Error unmarshalling received MCP config 
%v", err)
-                       continue
-               }
-               newCfg, err := a.mcpToPlanet(m)
-               if err != nil {
-                       log.Errorf("Invalid data: %v (%v)", err, 
string(rsc.Value))
-                       continue
-               }
-               if newCfg == nil {
-                       continue
-               }
-               received[newCfg.Namespace+"/"+newCfg.Name] = newCfg
-
-               newCfg.GroupVersionKind = groupVersionKind
-               oldCfg := a.Store.Get(newCfg.GroupVersionKind, newCfg.Name, 
newCfg.Namespace)
-
-               if oldCfg == nil {
-                       if _, err = a.Store.Create(*newCfg); err != nil {
-                               log.Errorf("Error adding a new resource to the 
store %v", err)
-                               continue
-                       }
-               } else if oldCfg.ResourceVersion != newCfg.ResourceVersion || 
newCfg.ResourceVersion == "" {
-                       // update the store only when resource version differs 
or unset.
-                       // newCfg.Annotations[mem.ResourceVersion] = 
newCfg.ResourceVersion
-                       newCfg.ResourceVersion = oldCfg.ResourceVersion
-                       if _, err = a.Store.Update(*newCfg); err != nil {
-                               log.Errorf("Error updating an existing resource 
in the store %v", err)
-                               continue
-                       }
-               }
-       }
-
-       // remove deleted resources from cache
-       for _, config := range existingConfigs {
-               if _, ok := received[config.Namespace+"/"+config.Name]; !ok {
-                       if err := a.Store.Delete(config.GroupVersionKind, 
config.Name, config.Namespace, nil); err != nil {
-                               log.Errorf("Error deleting an outdated resource 
from the store %v", err)
-                               continue
-                       }
-               }
-       }
-}
-
 // nolint: staticcheck
 func (a *ADSC) handleLDS(ll []*listener.Listener) {
        lh := map[string]*listener.Listener{}
diff --git a/pkg/adsc/util.go b/pkg/adsc/util.go
index f10e51f0..0e991593 100644
--- a/pkg/adsc/util.go
+++ b/pkg/adsc/util.go
@@ -18,10 +18,7 @@ package adsc
 
 import (
        "crypto/tls"
-       "strings"
 
-       "github.com/apache/dubbo-kubernetes/pkg/config"
-       "github.com/apache/dubbo-kubernetes/pkg/config/schema/collections"
        "github.com/apache/dubbo-kubernetes/pkg/security"
 )
 
@@ -53,22 +50,3 @@ func getClientCertFn(config *Config) func(requestInfo 
*tls.CertificateRequestInf
        return nil
 }
 
-func convertTypeURLToMCPGVK(typeURL string) (config.GroupVersionKind, bool) {
-       parts := strings.SplitN(typeURL, "/", 3)
-       if len(parts) != 3 {
-               return config.GroupVersionKind{}, false
-       }
-
-       gvk := config.GroupVersionKind{
-               Group:   parts[0],
-               Version: parts[1],
-               Kind:    parts[2],
-       }
-
-       _, isMCP := collections.Planet.FindByGroupVersionKind(gvk)
-       if isMCP {
-               return gvk, true
-       }
-
-       return config.GroupVersionKind{}, false
-}
diff --git a/pkg/config/schema/collections/collections.agent.go 
b/pkg/config/schema/collections/collections.agent.go
index d857de64..b2959b44 100644
--- a/pkg/config/schema/collections/collections.agent.go
+++ b/pkg/config/schema/collections/collections.agent.go
@@ -25,8 +25,8 @@ import (
        sigsk8siogatewayapiapisv1 "sigs.k8s.io/gateway-api/apis/v1"
        sigsk8siogatewayapiapisv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
 
+       dubboapimetav1alpha1 
"github.com/apache/dubbo-kubernetes/api/meta/v1alpha1"
        "github.com/apache/dubbo-kubernetes/pkg/config/schema/collection"
-       istioioapimetav1alpha1 "istio.io/api/meta/v1alpha1"
        istioioapinetworkingv1alpha3 "istio.io/api/networking/v1alpha3"
        istioioapisecurityv1beta1 "istio.io/api/security/v1beta1"
        k8sioapiadmissionregistrationv1 "k8s.io/api/admissionregistration/v1"
@@ -40,23 +40,23 @@ var (
                Plural:         "peerauthentications",
                Version:        "v1",
                VersionAliases: []string{},
-               Proto:          "istio.security.v1beta1.PeerAuthentication", 
StatusProto: "istio.meta.v1alpha1.IstioStatus",
-               ReflectType: 
reflect.TypeOf(&istioioapisecurityv1beta1.PeerAuthentication{}).Elem(), 
StatusType: reflect.TypeOf(&istioioapimetav1alpha1.IstioStatus{}).Elem(),
-               ProtoPackage: "istio.io/api/security/v1beta1", StatusPackage: 
"istio.io/api/meta/v1alpha1",
+               Proto:          "istio.security.v1beta1.PeerAuthentication", 
StatusProto: "istio.meta.v1alpha1.DubboStatus",
+               ReflectType: 
reflect.TypeOf(&istioioapisecurityv1beta1.PeerAuthentication{}).Elem(), 
StatusType: reflect.TypeOf(&dubboapimetav1alpha1.DubboStatus{}).Elem(),
+               ProtoPackage: "istio.io/api/security/v1beta1", StatusPackage: 
"github.com/apache/dubbo-kubernetes/api/meta/v1alpha1",
                ClusterScoped: false,
                Synthetic:     false,
                Builtin:       false,
        }.MustBuild()
-       SubsetRule = collection.Builder{
-               Identifier:     "SubsetRule",
+       DestinationRule = collection.Builder{
+               Identifier:     "DestinationRule",
                Group:          "networking.dubbo.apache.org",
-               Kind:           "SubsetRule",
-               Plural:         "subsetrules",
-               Version:        "v1",
+               Kind:           "DestinationRule",
+               Plural:         "destinationrules",
+               Version:        "v1alpha3",
                VersionAliases: []string{},
-               Proto:          "istio.networking.v1alpha3.DestinationRule", 
StatusProto: "istio.meta.v1alpha1.IstioStatus",
-               ReflectType: 
reflect.TypeOf(&istioioapinetworkingv1alpha3.DestinationRule{}).Elem(), 
StatusType: reflect.TypeOf(&istioioapimetav1alpha1.IstioStatus{}).Elem(),
-               ProtoPackage: "istio.io/api/networking/v1alpha3", 
StatusPackage: "istio.io/api/meta/v1alpha1",
+               Proto:          "istio.networking.v1alpha3.DestinationRule", 
StatusProto: "istio.meta.v1alpha1.DubboStatus",
+               ReflectType: 
reflect.TypeOf(&istioioapinetworkingv1alpha3.DestinationRule{}).Elem(), 
StatusType: reflect.TypeOf(&dubboapimetav1alpha1.DubboStatus{}).Elem(),
+               ProtoPackage: "istio.io/api/networking/v1alpha3", 
StatusPackage: "github.com/apache/dubbo-kubernetes/api/meta/v1alpha1",
                ClusterScoped: false,
                Synthetic:     false,
                Builtin:       false,
@@ -68,9 +68,9 @@ var (
                Plural:         "serviceroutes",
                Version:        "v1",
                VersionAliases: []string{},
-               Proto:          "istio.networking.v1alpha3.VirtualService", 
StatusProto: "istio.meta.v1alpha1.IstioStatus",
-               ReflectType: 
reflect.TypeOf(&istioioapinetworkingv1alpha3.VirtualService{}).Elem(), 
StatusType: reflect.TypeOf(&istioioapimetav1alpha1.IstioStatus{}).Elem(),
-               ProtoPackage: "istio.io/api/networking/v1alpha3", 
StatusPackage: "istio.io/api/meta/v1alpha1",
+               Proto:          "istio.networking.v1alpha3.VirtualService", 
StatusProto: "istio.meta.v1alpha1.DubboStatus",
+               ReflectType: 
reflect.TypeOf(&istioioapinetworkingv1alpha3.VirtualService{}).Elem(), 
StatusType: reflect.TypeOf(&dubboapimetav1alpha1.DubboStatus{}).Elem(),
+               ProtoPackage: "istio.io/api/networking/v1alpha3", 
StatusPackage: "github.com/apache/dubbo-kubernetes/api/meta/v1alpha1",
                ClusterScoped: false,
                Synthetic:     false,
                Builtin:       false,
@@ -146,7 +146,7 @@ var (
 
        Planet = collection.NewSchemasBuilder().
                MustAdd(PeerAuthentication).
-               MustAdd(SubsetRule).
+               MustAdd(DestinationRule).
                MustAdd(ServiceRoute).
                Build()
 
@@ -158,7 +158,7 @@ var (
 
        All = collection.NewSchemasBuilder().
                MustAdd(PeerAuthentication).
-               MustAdd(SubsetRule).
+               MustAdd(DestinationRule).
                MustAdd(ServiceRoute).
                MustAdd(MutatingWebhookConfiguration).
                MustAdd(ValidatingWebhookConfiguration).
diff --git a/pkg/config/schema/collections/collections.go 
b/pkg/config/schema/collections/collections.go
index eaf58844..5526ab90 100644
--- a/pkg/config/schema/collections/collections.go
+++ b/pkg/config/schema/collections/collections.go
@@ -25,8 +25,8 @@ import (
        sigsk8siogatewayapiapisv1 "sigs.k8s.io/gateway-api/apis/v1"
        sigsk8siogatewayapiapisv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
 
+       dubboapimetav1alpha1 
"github.com/apache/dubbo-kubernetes/api/meta/v1alpha1"
        "github.com/apache/dubbo-kubernetes/pkg/config/schema/collection"
-       istioioapimetav1alpha1 "istio.io/api/meta/v1alpha1"
        istioioapinetworkingv1alpha3 "istio.io/api/networking/v1alpha3"
        istioioapisecurityv1beta1 "istio.io/api/security/v1beta1"
        k8sioapiadmissionregistrationv1 "k8s.io/api/admissionregistration/v1"
@@ -40,23 +40,23 @@ var (
                Plural:         "peerauthentications",
                Version:        "v1",
                VersionAliases: []string{},
-               Proto:          "istio.security.v1beta1.PeerAuthentication", 
StatusProto: "istio.meta.v1alpha1.IstioStatus",
-               ReflectType: 
reflect.TypeOf(&istioioapisecurityv1beta1.PeerAuthentication{}).Elem(), 
StatusType: reflect.TypeOf(&istioioapimetav1alpha1.IstioStatus{}).Elem(),
-               ProtoPackage: "istio.io/api/security/v1beta1", StatusPackage: 
"istio.io/api/meta/v1alpha1",
+               Proto:          "istio.security.v1beta1.PeerAuthentication", 
StatusProto: "dubbo.meta.v1alpha1.DubboStatus",
+               ReflectType: 
reflect.TypeOf(&istioioapisecurityv1beta1.PeerAuthentication{}).Elem(), 
StatusType: reflect.TypeOf(&dubboapimetav1alpha1.DubboStatus{}).Elem(),
+               ProtoPackage: "istio.io/api/security/v1beta1", StatusPackage: 
"github.com/apache/dubbo-kubernetes/api/meta/v1alpha1",
                ClusterScoped: false,
                Synthetic:     false,
                Builtin:       false,
        }.MustBuild()
-       SubsetRule = collection.Builder{
-               Identifier:     "SubsetRule",
+       DestinationRule = collection.Builder{
+               Identifier:     "DestinationRule",
                Group:          "networking.dubbo.apache.org",
-               Kind:           "SubsetRule",
-               Plural:         "subsetrules",
-               Version:        "v1",
+               Kind:           "DestinationRule",
+               Plural:         "destinationrules",
+               Version:        "v1alpha3",
                VersionAliases: []string{},
-               Proto:          "istio.networking.v1alpha3.DestinationRule", 
StatusProto: "istio.meta.v1alpha1.IstioStatus",
-               ReflectType: 
reflect.TypeOf(&istioioapinetworkingv1alpha3.DestinationRule{}).Elem(), 
StatusType: reflect.TypeOf(&istioioapimetav1alpha1.IstioStatus{}).Elem(),
-               ProtoPackage: "istio.io/api/networking/v1alpha3", 
StatusPackage: "istio.io/api/meta/v1alpha1",
+               Proto:          "istio.networking.v1alpha3.DestinationRule", 
StatusProto: "dubbo.meta.v1alpha1.DubboStatus",
+               ReflectType: 
reflect.TypeOf(&istioioapinetworkingv1alpha3.DestinationRule{}).Elem(), 
StatusType: reflect.TypeOf(&dubboapimetav1alpha1.DubboStatus{}).Elem(),
+               ProtoPackage: "istio.io/api/networking/v1alpha3", 
StatusPackage: "github.com/apache/dubbo-kubernetes/api/meta/v1alpha1",
                ClusterScoped: false,
                Synthetic:     false,
                Builtin:       false,
@@ -68,9 +68,9 @@ var (
                Plural:         "serviceroutes",
                Version:        "v1",
                VersionAliases: []string{},
-               Proto:          "istio.networking.v1alpha3.VirtualService", 
StatusProto: "istio.meta.v1alpha1.IstioStatus",
-               ReflectType: 
reflect.TypeOf(&istioioapinetworkingv1alpha3.VirtualService{}).Elem(), 
StatusType: reflect.TypeOf(&istioioapimetav1alpha1.IstioStatus{}).Elem(),
-               ProtoPackage: "istio.io/api/networking/v1alpha3", 
StatusPackage: "istio.io/api/meta/v1alpha1",
+               Proto:          "istio.networking.v1alpha3.VirtualService", 
StatusProto: "dubbo.meta.v1alpha1.DubboStatus",
+               ReflectType: 
reflect.TypeOf(&istioioapinetworkingv1alpha3.VirtualService{}).Elem(), 
StatusType: reflect.TypeOf(&dubboapimetav1alpha1.DubboStatus{}).Elem(),
+               ProtoPackage: "istio.io/api/networking/v1alpha3", 
StatusPackage: "github.com/apache/dubbo-kubernetes/api/meta/v1alpha1",
                ClusterScoped: false,
                Synthetic:     false,
                Builtin:       false,
@@ -146,7 +146,7 @@ var (
 
        Planet = collection.NewSchemasBuilder().
                MustAdd(PeerAuthentication).
-               MustAdd(SubsetRule).
+               MustAdd(DestinationRule).
                MustAdd(ServiceRoute).
                Build()
 
@@ -158,7 +158,7 @@ var (
 
        All = collection.NewSchemasBuilder().
                MustAdd(PeerAuthentication).
-               MustAdd(SubsetRule).
+               MustAdd(DestinationRule).
                MustAdd(ServiceRoute).
                MustAdd(MutatingWebhookConfiguration).
                MustAdd(ValidatingWebhookConfiguration).
diff --git a/pkg/config/schema/gvk/resources.go 
b/pkg/config/schema/gvk/resources.go
index aee010d4..bcd12201 100644
--- a/pkg/config/schema/gvk/resources.go
+++ b/pkg/config/schema/gvk/resources.go
@@ -38,7 +38,7 @@ var (
        Pod                            = config.GroupVersionKind{Group: "", 
Version: "v1", Kind: "Pod"}
        MeshGlobalConfig               = config.GroupVersionKind{Group: "", 
Version: "v1alpha1", Kind: "MeshGlobalConfig"}
        PeerAuthentication             = config.GroupVersionKind{Group: 
"security.dubbo.apache.org", Version: "v1", Kind: "PeerAuthentication"}
-       SubsetRule                     = config.GroupVersionKind{Group: 
"networking.dubbo.apache.org", Version: "v1", Kind: "SubsetRule"}
+       DestinationRule                     = config.GroupVersionKind{Group: 
"networking.dubbo.apache.org", Version: "v1alpha3", Kind: "DestinationRule"}
        ServiceRoute                   = config.GroupVersionKind{Group: 
"networking.dubbo.apache.org", Version: "v1", Kind: "ServiceRoute"}
        EndpointSlice                  = config.GroupVersionKind{Group: 
"discovery.k8s.io", Version: "v1", Kind: "EndpointSlice"}
        Endpoints                      = config.GroupVersionKind{Group: "", 
Version: "v1", Kind: "Endpoints"}
@@ -79,8 +79,8 @@ func ToGVR(g config.GroupVersionKind) 
(schema.GroupVersionResource, bool) {
                return gvr.MeshGlobalConfig, true
        case PeerAuthentication:
                return gvr.PeerAuthentication, true
-       case SubsetRule:
-               return gvr.SubsetRule, true
+       case DestinationRule:
+               return gvr.DestinationRule, true
        case ServiceRoute:
                return gvr.ServiceRoute, true
        case EndpointSlice:
@@ -119,8 +119,8 @@ func FromGVR(g schema.GroupVersionResource) 
(config.GroupVersionKind, bool) {
                return PeerAuthentication, true
        case gvr.ServiceRoute:
                return ServiceRoute, true
-       case gvr.SubsetRule:
-               return SubsetRule, true
+       case gvr.DestinationRule:
+               return DestinationRule, true
        case gvr.EndpointSlice:
                return EndpointSlice, true
        case gvr.Endpoints:
diff --git a/pkg/config/schema/gvr/resources.go 
b/pkg/config/schema/gvr/resources.go
index 8e860ff9..08d627b6 100644
--- a/pkg/config/schema/gvr/resources.go
+++ b/pkg/config/schema/gvr/resources.go
@@ -35,7 +35,7 @@ var (
        ServiceAccount                 = schema.GroupVersionResource{Group: "", 
Version: "v1", Resource: "serviceaccounts"}
        MeshGlobalConfig               = schema.GroupVersionResource{Group: "", 
Version: "v1alpha1", Resource: "meshglobalconfigs"}
        PeerAuthentication             = schema.GroupVersionResource{Group: 
"security.dubbo.apache.org", Version: "v1", Resource: "peerauthentications"}
-       SubsetRule                     = schema.GroupVersionResource{Group: 
"networking.dubbo.apache.org", Version: "v1", Resource: "subsetrules"}
+       DestinationRule                     = 
schema.GroupVersionResource{Group: "networking.dubbo.apache.org", Version: 
"v1alpha3", Resource: "destinationrules"}
        ServiceRoute                   = schema.GroupVersionResource{Group: 
"networking.dubbo.apache.org", Version: "v1", Resource: "serviceroutes"}
        EndpointSlice                  = schema.GroupVersionResource{Group: 
"discovery.k8s.io", Version: "v1", Resource: "endpointslices"}
        Endpoints                      = schema.GroupVersionResource{Group: "", 
Version: "v1", Resource: "endpoints"}
@@ -65,7 +65,7 @@ func IsClusterScoped(g schema.GroupVersionResource) bool {
                return false
        case PeerAuthentication:
                return false
-       case SubsetRule:
+       case DestinationRule:
                return false
        case ServiceRoute:
                return false
diff --git a/pkg/config/schema/kind/resources.go 
b/pkg/config/schema/kind/resources.go
index 08e14e4b..02b94b07 100644
--- a/pkg/config/schema/kind/resources.go
+++ b/pkg/config/schema/kind/resources.go
@@ -32,7 +32,7 @@ const (
        MutatingWebhookConfiguration
        PeerAuthentication
        ServiceRoute
-       SubsetRule
+       DestinationRule
        Gateway
        GatewayClass
        HTTPRoute
@@ -68,8 +68,8 @@ func (k Kind) String() string {
                return "PeerAuthentication"
        case ServiceRoute:
                return "ServiceRoute"
-       case SubsetRule:
-               return "SubsetRule"
+       case DestinationRule:
+               return "DestinationRule"
        case GatewayClass:
                return "GatewayClass"
        case Gateway:
diff --git a/pkg/config/schema/kubeclient/resources.go 
b/pkg/config/schema/kubeclient/resources.go
index 3fcc5670..5849a396 100644
--- a/pkg/config/schema/kubeclient/resources.go
+++ b/pkg/config/schema/kubeclient/resources.go
@@ -120,7 +120,7 @@ func gvrToObject(g schema.GroupVersionResource) 
runtime.Object {
                return &apiistioioapisecurityv1.PeerAuthentication{}
        case gvr.ServiceRoute:
                return &apiistioioapinetworkingv1.VirtualService{}
-       case gvr.SubsetRule:
+       case gvr.DestinationRule:
                return &apiistioioapinetworkingv1.DestinationRule{}
        case gvr.GatewayClass:
                return &sigsk8siogatewayapiapisv1.GatewayClass{}
@@ -243,35 +243,35 @@ func getInformerFiltered(c ClientGetter, opts 
ktypes.InformerOptions, g schema.G
                w = func(options metav1.ListOptions) (watch.Interface, error) {
                        return 
c.Dynamic().Resource(gvr).Namespace(opts.Namespace).Watch(context.Background(), 
options)
                }
-       case gvr.SubsetRule:
-               // SubsetRule uses networking.dubbo.apache.org API group, not 
networking.istio.io
+       case gvr.DestinationRule:
+               // DestinationRule uses networking.dubbo.apache.org API group, 
not networking.istio.io
                // Use Dynamic client to access it
                gvr := schema.GroupVersionResource{
                        Group:    "networking.dubbo.apache.org",
-                       Version:  "v1",
-                       Resource: "subsetrules",
+                       Version:  "v1alpha3",
+                       Resource: "destinationrules",
                }
                l = func(options metav1.ListOptions) (runtime.Object, error) {
                        // Log the namespace being watched for diagnosis
                        if opts.Namespace == "" {
-                               log.Infof("SubsetRule informer: List called for 
all namespaces")
+                               log.Infof("DestinationRule informer: List 
called for all namespaces")
                        } else {
-                               log.Infof("SubsetRule informer: List called for 
namespace %s", opts.Namespace)
+                               log.Infof("DestinationRule informer: List 
called for namespace %s", opts.Namespace)
                        }
                        return 
c.Dynamic().Resource(gvr).Namespace(opts.Namespace).List(context.Background(), 
options)
                }
                w = func(options metav1.ListOptions) (watch.Interface, error) {
                        // Log the namespace being watched for diagnosis
                        if opts.Namespace == "" {
-                               log.Infof("SubsetRule informer: Watch called 
for all namespaces")
+                               log.Infof("DestinationRule informer: Watch 
called for all namespaces")
                        } else {
-                               log.Infof("SubsetRule informer: Watch called 
for namespace %s", opts.Namespace)
+                               log.Infof("DestinationRule informer: Watch 
called for namespace %s", opts.Namespace)
                        }
                        watchInterface, err := 
c.Dynamic().Resource(gvr).Namespace(opts.Namespace).Watch(context.Background(), 
options)
                        if err != nil {
-                               log.Errorf("SubsetRule informer: Watch failed: 
%v", err)
+                               log.Errorf("DestinationRule informer: Watch 
failed: %v", err)
                        } else {
-                               log.Infof("SubsetRule informer: Watch 
connection established successfully")
+                               log.Infof("DestinationRule informer: Watch 
connection established successfully")
                        }
                        return watchInterface, err
                }
diff --git a/pkg/config/schema/kubetypes/resources.go 
b/pkg/config/schema/kubetypes/resources.go
index 993774c7..c5721a57 100644
--- a/pkg/config/schema/kubetypes/resources.go
+++ b/pkg/config/schema/kubetypes/resources.go
@@ -41,7 +41,7 @@ func getGvk(obj any) (config.GroupVersionKind, bool) {
        case *apiistioioapisecurityv1.PeerAuthentication:
                return gvk.PeerAuthentication, true
        case *apiistioioapinetworkingv1.DestinationRule:
-               return gvk.SubsetRule, true
+               return gvk.DestinationRule, true
        case *apiistioioapinetworkingv1.VirtualService:
                return gvk.ServiceRoute, true
        case *k8sioapicorev1.ConfigMap:
diff --git a/pkg/kube/inject/inject.go b/pkg/kube/inject/inject.go
index 716750ee..b538ba59 100644
--- a/pkg/kube/inject/inject.go
+++ b/pkg/kube/inject/inject.go
@@ -25,9 +25,9 @@ import (
        "strings"
        "text/template"
 
+       "github.com/apache/dubbo-kubernetes/api/annotation"
        meshv1alpha1 "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
        common_features "github.com/apache/dubbo-kubernetes/pkg/features"
-       "istio.io/api/annotation"
        corev1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/apimachinery/pkg/types"
@@ -213,7 +213,7 @@ func getProxyImage(values map[string]any, defaultImage 
string) string {
 }
 
 func selectTemplates(params InjectionParameters) []string {
-       if a, f := params.pod.Annotations[annotation.InjectTemplates.Name]; f {
+       if a, f := 
params.pod.Annotations[annotation.OrgApacheDubboInjectTemplates.Name]; f {
                names := []string{}
                for _, tmplName := range strings.Split(a, ",") {
                        name := strings.TrimSpace(tmplName)
@@ -280,7 +280,7 @@ func stripPod(req InjectionParameters) *corev1.Pod {
                pod.Spec.Containers = modifyContainers(pod.Spec.Containers, c, 
Remove)
        }
 
-       delete(pod.Annotations, annotation.SidecarStatus.Name)
+       delete(pod.Annotations, annotation.OrgApacheDubboProxylessStatus.Name)
 
        return pod
 }
@@ -337,8 +337,8 @@ func injectRequired(ignored []string, config *Config, 
podSpec *corev1.PodSpec, m
        var useDefault bool
        var inject bool
 
-       objectSelector := annos["proxyless.dubbo.apache.org/inject"]
-       if lbl, labelPresent := 
metadata.GetLabels()["proxyless.dubbo.apache.org/inject"]; labelPresent {
+       objectSelector := annos[annotation.OrgApacheDubboProxylessInject.Name]
+       if lbl, labelPresent := 
metadata.GetLabels()[annotation.OrgApacheDubboProxylessInject.Name]; 
labelPresent {
                // The label is the new API; if both are present we prefer the 
label
                objectSelector = lbl
        }
@@ -351,7 +351,7 @@ func injectRequired(ignored []string, config *Config, 
podSpec *corev1.PodSpec, m
                useDefault = true
        default:
                log.Warnf("Invalid value for %s: %q. Only 'true' and 'false' 
are accepted. Falling back to default injection policy.",
-                       "proxyless.dubbo.apache.org/inject", objectSelector)
+                       annotation.OrgApacheDubboProxylessInject.Name, 
objectSelector)
                useDefault = true
        }
 
@@ -381,7 +381,7 @@ func injectRequired(ignored []string, config *Config, 
podSpec *corev1.PodSpec, m
 func injectionStatus(pod *corev1.Pod) *InjectionStatus {
        var statusBytes []byte
        if pod.ObjectMeta.Annotations != nil {
-               if value, ok := 
pod.ObjectMeta.Annotations[annotation.SidecarStatus.Name]; ok {
+               if value, ok := 
pod.ObjectMeta.Annotations[annotation.OrgApacheDubboProxylessStatus.Name]; ok {
                        statusBytes = []byte(value)
                }
        }
@@ -416,7 +416,7 @@ func reinsertOverrides(pod *corev1.Pod) (*corev1.Pod, 
error) {
        }
 
        existingOverrides := podOverrides{}
-       if annotationOverrides, f := 
pod.Annotations[annotation.ProxyOverrides.Name]; f {
+       if annotationOverrides, f := 
pod.Annotations[annotation.OrgApacheDubboProxyOverrides.Name]; f {
                if err := json.Unmarshal([]byte(annotationOverrides), 
&existingOverrides); err != nil {
                        return nil, err
                }
diff --git a/pkg/kube/inject/webhook.go b/pkg/kube/inject/webhook.go
index 9ede17f3..133f1bea 100644
--- a/pkg/kube/inject/webhook.go
+++ b/pkg/kube/inject/webhook.go
@@ -30,15 +30,13 @@ import (
        "text/template"
        "time"
 
+       meshv1alpha1 "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
        "github.com/apache/dubbo-kubernetes/dubbod/planet/pkg/model"
        opconfig "github.com/apache/dubbo-kubernetes/operator/pkg/apis"
-       "github.com/apache/dubbo-kubernetes/pkg/config/mesh"
        "github.com/apache/dubbo-kubernetes/pkg/kube"
        "github.com/apache/dubbo-kubernetes/pkg/kube/multicluster"
        "github.com/apache/dubbo-kubernetes/pkg/util/protomarshal"
        "gomodules.xyz/jsonpatch/v2"
-       "istio.io/api/annotation"
-       meshconfig "istio.io/api/mesh/v1alpha1"
        corev1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/apimachinery/pkg/runtime"
@@ -67,7 +65,7 @@ var (
 type Webhook struct {
        mu           sync.RWMutex
        watcher      Watcher
-       meshConfig   *meshconfig.MeshConfig
+       meshConfig   *meshv1alpha1.MeshGlobalConfig
        env          *model.Environment
        Config       *Config
        valuesConfig ValuesConfig
@@ -97,8 +95,8 @@ type InjectionParameters struct {
        templates           map[string]*template.Template
        defaultTemplate     []string
        aliases             map[string][]string
-       meshConfig          *meshconfig.MeshConfig
-       proxyConfig         *meshconfig.ProxyConfig
+       meshGlobalConfig    *meshv1alpha1.MeshGlobalConfig
+       proxyConfig         *meshv1alpha1.ProxyConfig
        valuesConfig        ValuesConfig
        revision            string
        proxyEnvs           map[string]string
@@ -267,7 +265,7 @@ func (wh *Webhook) inject(ar *kube.AdmissionReview, path 
string) *kube.Admission
                templates:           wh.Config.Templates,
                defaultTemplate:     wh.Config.DefaultTemplates,
                aliases:             wh.Config.Aliases,
-               meshConfig:          wh.meshConfig,
+               meshGlobalConfig:    wh.meshConfig,
                proxyConfig:         proxyConfig,
                valuesConfig:        wh.valuesConfig,
                injectedAnnotations: wh.Config.InjectedAnnotations,
@@ -454,29 +452,9 @@ func addApplicationContainerConfig(pod *corev1.Pod) {
 }
 
 func reorderPod(pod *corev1.Pod, req InjectionParameters) error {
-       var merr error
-       mc := req.meshConfig
-       // Get copy of pod proxyconfig, to determine container ordering
-       if pca, f := 
req.pod.ObjectMeta.GetAnnotations()[annotation.ProxyConfig.Name]; f {
-               mc, merr = mesh.ApplyProxyConfig(pca, req.meshConfig)
-               if merr != nil {
-                       return merr
-               }
-       }
-
-       // nolint: staticcheck
-       holdPod := 
mc.GetDefaultConfig().GetHoldApplicationUntilProxyStarts().GetValue()
-
-       proxyLocation := MoveLast
-       // If HoldApplicationUntilProxyStarts is set, reorder the proxy location
-       if holdPod {
-               proxyLocation = MoveFirst
-       }
-
-       // Proxy container should be last, unless 
HoldApplicationUntilProxyStarts is set
-       // This is to ensure `kubectl exec` and similar commands continue to 
default to the user's container
-       pod.Spec.Containers = modifyContainers(pod.Spec.Containers, 
ProxyContainerName, proxyLocation)
-
+       // Proxy container should be last to ensure `kubectl exec` and similar 
commands
+       // continue to default to the user's container
+       pod.Spec.Containers = modifyContainers(pod.Spec.Containers, 
ProxyContainerName, MoveLast)
        return nil
 }
 
diff --git a/samples/grpc-app/README.md b/samples/grpc-app/README.md
index 42516e91..fe7c8f25 100644
--- a/samples/grpc-app/README.md
+++ b/samples/grpc-app/README.md
@@ -55,14 +55,14 @@ grpcurl -plaintext -d '{"url": 
"xds:///provider.grpc-app.svc.cluster.local:7070"
 
 ## Traffic Management
 
-### Creating subsets with SubsetRule
+### Creating subsets with DestinationRule
 
 First, create a subset for each version of the workload to enable traffic 
splitting:
 
 ```bash
 cat <<EOF | kubectl apply -f -
-apiVersion: networking.dubbo.apache.org/v1
-kind: SubsetRule
+apiVersion: networking.dubbo.apache.org/v1alpha3
+kind: DestinationRule
 metadata:
   name: provider-versions
   namespace: grpc-app
@@ -84,7 +84,7 @@ Using the subsets defined above, you can send weighted 
traffic to different vers
 
 ```bash
 cat <<EOF | kubectl apply -f -
-apiVersion: networking.dubbo.apache.org/v1
+apiVersion: networking.dubbo.apache.org/v1alpha3
 kind: ServiceRoute
 metadata:
   name: provider-weights
@@ -131,12 +131,12 @@ Due to the changes to the application itself required to 
enable security in gRPC
 
 ### Enable client-side mTLS
 
-To enable client-side mTLS, apply a `SubsetRule` with `tls` settings:
+To enable client-side mTLS, apply a `DestinationRule` with `tls` settings:
 
 ```bash
 cat <<EOF | kubectl apply -f -
-apiVersion: networking.dubbo.apache.org/v1
-kind: SubsetRule
+apiVersion: networking.dubbo.apache.org/v1alpha3
+kind: DestinationRule
 metadata:
   name: provider-mtls
   namespace: grpc-app
diff --git a/tests/grpc-app/consumer/main.go b/tests/grpc-app/consumer/main.go
index 95fed0e3..c5dad251 100644
--- a/tests/grpc-app/consumer/main.go
+++ b/tests/grpc-app/consumer/main.go
@@ -365,12 +365,12 @@ func (s *testServerImpl) ForwardEcho(ctx context.Context, 
req *pb.ForwardEchoReq
                // Double-check after acquiring write lock
                if cached, exists = s.connCache[req.Url]; !exists || cached == 
nil || cached.conn == nil {
                        conn = nil
-                       // When TLS is configured (SubsetRule ISTIO_MUTUAL), 
gRPC xDS client needs
+                       // When TLS is configured (DestinationRule 
ISTIO_MUTUAL), gRPC xDS client needs
                        // to fetch certificates from CertificateProvider. The 
CertificateProvider uses file_watcher
                        // to read certificate files. If the files are not 
ready or CertificateProvider is not
                        // initialized, certificate fetching will timeout.
                        // We wait a short time to ensure CertificateProvider 
is ready and certificate files are accessible.
-                       // This is especially important when SubsetRule is just 
created and TLS is enabled.
+                       // This is especially important when DestinationRule is 
just created and TLS is enabled.
                        // The CertificateProvider may need time to initialize, 
especially on first connection.
                        // We wait 3 seconds to give CertificateProvider enough 
time to initialize (reduced from 5s for faster startup).
                        log.Printf("ForwardEcho: waiting 3 seconds to ensure 
CertificateProvider is ready...")
@@ -391,7 +391,7 @@ func (s *testServerImpl) ForwardEcho(ctx context.Context, 
req *pb.ForwardEchoReq
 
                        // Dial with xDS URL - use background context, not the 
request context
                        // The request context might timeout before xDS 
configuration is received
-                       // When TLS is configured (SubsetRule ISTIO_MUTUAL), 
gRPC xDS client needs
+                       // When TLS is configured (DestinationRule 
ISTIO_MUTUAL), gRPC xDS client needs
                        // to fetch certificates from CertificateProvider. This 
may take time, especially on
                        // first connection. We use a longer timeout context to 
allow certificate fetching.
                        log.Printf("ForwardEcho: creating new connection for 
%s...", req.Url)
@@ -427,7 +427,7 @@ func (s *testServerImpl) ForwardEcho(ctx context.Context, 
req *pb.ForwardEchoReq
        // was established before xDS config was received, it might be using 
FallbackCreds (plaintext).
        // We'll proceed with RPC calls, but if they fail with TLS/plaintext 
mismatch errors,
        // we'll clear the cache and retry.
-       // When TLS is configured (SubsetRule ISTIO_MUTUAL), gRPC xDS client 
needs
+       // When TLS is configured (DestinationRule ISTIO_MUTUAL), gRPC xDS 
client needs
        // to fetch certificates from CertificateProvider during TLS handshake. 
The TLS handshake
        // happens when the connection state transitions to READY. If 
CertificateProvider is not ready,
        // the TLS handshake will timeout. We need to wait for the connection 
to be READY, which
@@ -595,7 +595,7 @@ func (s *testServerImpl) ForwardEcho(ctx context.Context, 
req *pb.ForwardEchoReq
                        // 1. If client config changed (plaintext -> TLS), new 
connection uses TLS
                        // 2. If server config changed (TLS -> plaintext), new 
connection uses plaintext
                        // 3. Connection behavior is consistent with current 
xDS configuration
-                       // - When only client TLS (SubsetRule ISTIO_MUTUAL) but 
server plaintext: connection SHOULD FAIL
+                       // - When only client TLS (DestinationRule 
ISTIO_MUTUAL) but server plaintext: connection SHOULD FAIL
                        // - When client TLS + server mTLS (PeerAuthentication 
STRICT): connection SHOULD SUCCEED
                        // - When both plaintext: connection SHOULD SUCCEED
                        // By clearing cache and reconnecting, we ensure 
connection uses current xDS config.
@@ -613,8 +613,8 @@ func (s *testServerImpl) ForwardEcho(ctx context.Context, 
req *pb.ForwardEchoReq
                                        log.Printf("ForwardEcho: WARNING - 
detected TLS/plaintext mismatch error: %v", err)
                                        log.Printf("ForwardEcho: NOTE - This 
error indicates that client and server TLS configuration are mismatched")
                                        log.Printf("ForwardEcho: This usually 
happens when:")
-                                       log.Printf("ForwardEcho:   1. 
SubsetRule with ISTIO_MUTUAL exists but PeerAuthentication with STRICT does not 
(client TLS, server plaintext)")
-                                       log.Printf("ForwardEcho:   2. 
SubsetRule was deleted but cached connection still uses TLS")
+                                       log.Printf("ForwardEcho:   1. 
DestinationRule with ISTIO_MUTUAL exists but PeerAuthentication with STRICT 
does not (client TLS, server plaintext)")
+                                       log.Printf("ForwardEcho:   2. 
DestinationRule was deleted but cached connection still uses TLS")
                                        log.Printf("ForwardEcho: Clearing 
connection cache to force reconnection with updated xDS config...")
                                }
 
diff --git a/tools/metadata/main.go b/tools/metadata/main.go
new file mode 100644
index 00000000..04aa67ca
--- /dev/null
+++ b/tools/metadata/main.go
@@ -0,0 +1,485 @@
+package main
+
+import (
+       "bytes"
+       "flag"
+       "fmt"
+       "log"
+       "os"
+       "path/filepath"
+       "regexp"
+       "sort"
+       "strings"
+       "text/template"
+
+       "github.com/gomarkdown/markdown"
+       "github.com/gomarkdown/markdown/html"
+       "github.com/gomarkdown/markdown/parser"
+       "github.com/spf13/cobra"
+       "sigs.k8s.io/yaml"
+)
+
+const (
+       outputTemplate = `
+// GENERATED FILE -- DO NOT EDIT
+
+package {{ .Package }}
+
+type FeatureStatus int
+
+const (
+       Alpha FeatureStatus = iota
+       Beta
+       Stable
+)
+
+func (s FeatureStatus) String() string {
+       switch s {
+       case Alpha:
+               return "Alpha"
+       case Beta:
+               return "Beta"
+       case Stable:
+               return "Stable"
+       }
+       return "Unknown"
+}
+
+type ResourceTypes int
+
+const (
+       Unknown ResourceTypes = iota
+       {{- range .KnownTypes }}
+    {{ . }}
+    {{- end }}
+)
+
+func (r ResourceTypes) String() string {
+       switch r {
+       {{- range $i, $t := .KnownTypes }}
+       case {{ add $i 1 }}:
+               return "{{$t}}"
+       {{- end }}
+       }
+       return "Unknown"
+}
+
+// Instance describes a single resource {{ .Collection.NameLowercase }}
+type Instance struct {
+       // The name of the {{ .Collection.NameLowercase }}.
+       Name string
+
+       // Description of the {{ .Collection.NameLowercase }}.
+       Description string
+
+       // FeatureStatus of this {{ .Collection.NameLowercase }}.
+       FeatureStatus FeatureStatus
+
+       // Hide the existence of this {{ .Collection.NameLowercase }} when 
outputting usage information.
+       Hidden bool
+
+       // Mark this {{ .Collection.NameLowercase }} as deprecated when 
generating usage information.
+       Deprecated bool
+
+       // The types of resources this {{ .Collection.NameLowercase }} applies 
to.
+       Resources []ResourceTypes
+}
+
+var (
+{{ range .Variables }}
+       {{ .GoName }} = Instance {
+               Name:          "{{ .Name }}",
+               Description:   {{ processGoDescription .Description 24 }},
+               FeatureStatus: {{ .FeatureStatus }},
+               Hidden:        {{ .Hidden }},
+               Deprecated:    {{ .Deprecated }},
+               Resources: []ResourceTypes{
+                       {{- range .Resources }}
+                       {{ . }},
+                       {{- end }}
+               },
+       }
+{{ end }}
+)
+
+func AllResource{{ .Collection.NamePlural }}() []*Instance {
+       return []*Instance {
+               {{- range .Variables }}
+               &{{ .GoName }},
+               {{- end }}
+       }
+}
+
+func AllResourceTypes() []string {
+       return []string {
+               {{- range .KnownTypes }}
+               "{{ . }}",
+               {{- end }}
+       }
+}
+`
+)
+
+type FeatureStatus string
+
+const (
+       Alpha  FeatureStatus = "Alpha"
+       Beta   FeatureStatus = "Beta"
+       Stable FeatureStatus = "Stable"
+)
+
+type Collection struct {
+       Name                string
+       NamePlural          string
+       NameLowercase       string
+       NameLowercasePlural string
+       ConceptLink         string
+}
+
+var (
+       annotations = Collection{
+               Name:                "Annotation",
+               NamePlural:          "Annotations",
+               NameLowercase:       "annotation",
+               NameLowercasePlural: "annotations",
+               ConceptLink:         
"https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/";,
+       }
+
+       labels = Collection{
+               Name:                "Label",
+               NamePlural:          "Labels",
+               NameLowercase:       "label",
+               NameLowercasePlural: "labels",
+               ConceptLink:         
"https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/";,
+       }
+)
+
+func collectionForType(typ string) (Collection, error) {
+       switch typ {
+       case annotations.NameLowercase:
+               return annotations, nil
+       case labels.NameLowercase:
+               return labels, nil
+       default:
+               return Collection{}, fmt.Errorf("unrecognized variable_type: 
%s", typ)
+       }
+}
+
+var (
+       input          string
+       output         string
+       collectionType string
+       collection     Collection
+
+       nameSeparator = regexp.MustCompile(`[._\-]`)
+
+       rootCmd = cobra.Command{
+               Use:   "metadata",
+               Short: "Generates a Go source file and HTML file containing 
annotations/labels.",
+               Long: "Generates a Go source file and HTML file containing 
annotation/label definitions based " +
+                       "on an input YAML file.",
+               Run: func(cmd *cobra.Command, args []string) {
+                       processFlags()
+                       yamlContent, err := os.ReadFile(input)
+                       if err != nil {
+                               log.Fatalf("unable to read input YAML file: 
%v", err)
+                       }
+
+                       // Unmarshal the file.
+                       var variables []Variable
+                       switch collectionType {
+                       case annotations.NameLowercase:
+                               var cfg AnnotationConfiguration
+                               if err = yaml.Unmarshal(yamlContent, &cfg); err 
!= nil {
+                                       log.Fatalf("error parsing input YAML 
file: %v", err)
+                               }
+                               variables = cfg.Variables
+                       case labels.NameLowercase:
+                               var cfg LabelConfiguration
+                               if err = yaml.Unmarshal(yamlContent, &cfg); err 
!= nil {
+                                       log.Fatalf("error parsing input YAML 
file: %v", err)
+                               }
+                               variables = cfg.Variables
+                       default:
+                               log.Fatalf("invalid value for collection_type: 
%s", collectionType)
+                       }
+
+                       // Find all the known resource types
+                       m := make(map[string]bool)
+                       for _, a := range variables {
+                               for _, r := range a.Resources {
+                                       m[r] = true
+                               }
+                       }
+                       knownTypes := make([]string, 0, len(m))
+                       for k := range m {
+                               knownTypes = append(knownTypes, k)
+                       }
+                       sort.Strings(knownTypes)
+
+                       // Process/cleanup the values read in from YAML.
+                       for i := range variables {
+                               if variables[i].Name == "" {
+                                       log.Fatalf("variable %d in input YAML 
file missing name", i)
+                               }
+
+                               // Generate sensible defaults for values if not 
provided in the yaml.
+                               variables[i].GoName = 
generateVariableName(variables[i])
+                               variables[i].FeatureStatus = 
generateFeatureStatus(variables[i])
+                       }
+
+                       // sort by name
+                       sort.Slice(variables, func(i, j int) bool {
+                               return strings.Compare(variables[i].Name, 
variables[j].Name) < 0
+                       })
+
+                       // Create the output file template.
+                       t, err := 
template.New("varTemplate").Funcs(template.FuncMap{
+                               "processGoDescription": processGoDescription, 
"add": add,
+                       }).Parse(outputTemplate)
+                       if err != nil {
+                               log.Fatalf("failed parsing variable template: 
%v", err)
+                       }
+
+                       // Generate the Go source.
+                       var goSource bytes.Buffer
+                       if err := t.Execute(&goSource, map[string]interface{}{
+                               "Package":    getPackage(),
+                               "KnownTypes": knownTypes,
+                               "Variables":  variables,
+                               "Collection": collection,
+                       }); err != nil {
+                               log.Fatalf("failed generating output Go source 
code %s: %v", output, err)
+                       }
+
+                       if err := os.WriteFile(output, goSource.Bytes(), 
0o666); err != nil {
+                               log.Fatalf("Failed writing to output file %s: 
%v", output, err)
+                       }
+               },
+       }
+)
+
+func init() {
+       rootCmd.PersistentFlags().StringVar(&input, "input", "",
+               "Input YAML file to be parsed.")
+       rootCmd.PersistentFlags().StringVar(&output, "output", "",
+               "Output Go file to be generated.")
+       rootCmd.PersistentFlags().StringVar(&collectionType, "collection_type", 
annotations.NameLowercase,
+               fmt.Sprintf("Output type for the generated collection. Allowed 
values are '%s' or '%s'.",
+                       annotations.NameLowercase, labels.NameLowercase))
+       flag.CommandLine.VisitAll(func(gf *flag.Flag) {
+               rootCmd.PersistentFlags().AddGoFlag(gf)
+       })
+}
+
+func processFlags() {
+       var err error
+       collection, err = collectionForType(collectionType)
+       if err != nil {
+               log.Fatal(err)
+       }
+}
+
+func main() {
+       if err := rootCmd.Execute(); err != nil {
+               os.Exit(-1)
+       }
+}
+
+type Variable struct {
+       // The name of the generated golang variable.
+       GoName string `json:"variableName"`
+
+       // The name of the collection variable.
+       Name string `json:"name"`
+
+       // FeatureStatus of the collection variable.
+       FeatureStatus string `json:"featureStatus"`
+
+       // Description of the collection variable.
+       Description string `json:"description"`
+
+       // Hide the existence of this collection variable when outputting usage 
information.
+       Hidden bool `json:"hidden"`
+
+       // Mark this annotation as deprecated when generating usage information.
+       Deprecated bool `json:"deprecated"`
+
+       // Indicates the types of resources this collection variable can be 
applied to.
+       Resources []string `json:"resources"`
+}
+
+type AnnotationConfiguration struct {
+       Variables []Variable `json:"annotations"`
+}
+
+type LabelConfiguration struct {
+       Variables []Variable `json:"labels"`
+}
+
+func getPackage() string {
+       path, _ := filepath.Abs(output)
+       return filepath.Base(filepath.Dir(path))
+}
+
+func generateVariableName(v Variable) string {
+       if len(v.GoName) > 0 {
+               return v.GoName
+       }
+
+       // Split the annotation name to separate the namespace/name portions.
+       parts := strings.Split(v.Name, "/")
+       ns := parts[0]
+       name := parts[1]
+
+       // First, process the namespace portion ...
+
+       // Strip .istio.io from the namespace portion of the annotation name.
+       ns = strings.TrimSuffix(ns, ".istio.io")
+
+       // Separate the words by spaces and capitalize each word.
+       ns = strings.ReplaceAll(ns, ".", " ")
+       // nolint: staticcheck
+       ns = strings.Title(ns)
+
+       // Reverse the namespace words so that they increase in specificity 
from left to right.
+       nsParts := strings.Split(ns, " ")
+       ns = ""
+       for i := len(nsParts) - 1; i >= 0; i-- {
+               ns += nsParts[i]
+       }
+
+       // Now, process the name portion ...
+
+       // Separate the words with spaces and capitalize each word.
+       name = nameSeparator.ReplaceAllString(name, " ")
+       // nolint: staticcheck
+       name = strings.Title(name)
+
+       // Remove the spaces to generate a camel case variable name.
+       name = strings.ReplaceAll(name, " ", "")
+
+       // Concatenate the names together.
+       return ns + name
+}
+
+func getFeatureStatus(fs string) (FeatureStatus, error) {
+       // nolint: staticcheck
+       asTitle := strings.Title(fs)
+       switch FeatureStatus(asTitle) {
+       case Alpha:
+               return Alpha, nil
+       case Beta:
+               return Beta, nil
+       case Stable:
+               return Stable, nil
+       }
+       return "", fmt.Errorf("invalid feature status string: `%s` 
(stings.Title=`%s`)", fs, asTitle)
+}
+
+func generateFeatureStatus(v Variable) string {
+       if len(v.FeatureStatus) > 0 {
+               fs, err := getFeatureStatus(v.FeatureStatus)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               return string(fs)
+       }
+
+       // If the name begins with the feature status, use it.
+       firstPart := strings.Split(v.Name, ".")
+       fs, err := getFeatureStatus(firstPart[0])
+       if err == nil {
+               return string(fs)
+       }
+
+       // Default to Alpha
+       return string(Alpha)
+}
+
+func processHTMLDescription(in string) string {
+       // In most cases, the description is a single line in Markdown format.
+       // Convert it to HTML with a Markdown parser, this will give us a 
better looking output.
+       return string(mdToHTML([]byte(in)))
+}
+
+func processGoDescription(in string, indent int) string {
+       if strings.Contains(in, "\n") {
+               return lineWrap(in)
+       }
+       return wordWrap(in, indent)
+}
+
+func wordWrap(in string, indent int) string {
+       // We use double quotes (") around each line, so replace any double 
quotes embedded
+       // in the string with back ticks (`).
+       in = strings.ReplaceAll(in, "\"", "`")
+
+       indentPrefix := strings.Repeat(" ", indent)
+       words := strings.Split(in, " ")
+
+       maxLineLength := 80
+
+       out := ""
+       line := ""
+       for len(words) > 0 {
+               // Take the next word.
+               word := words[0]
+               words = words[1:]
+
+               if indent+len(line)+len(word) > maxLineLength {
+                       // Need to word wrap - emit the current line.
+                       out += "\"" + line + " \""
+                       line = ""
+
+                       // Wrap to the start of the next line.
+                       out += "+\n" + indentPrefix
+               }
+
+               // Add the word to the current line.
+               if len(line) > 0 {
+                       line += " "
+               }
+               line += word
+       }
+
+       // Emit the final line
+       out += "\"" + line + "\""
+
+       return out
+}
+
+func lineWrap(in string) string {
+       // We use back tick (`) around the entire string, so replace any back 
ticks embedded
+       // in the string with double quotes (").
+       in = strings.ReplaceAll(in, "`", "\"")
+
+       lines := strings.Split(in, "\n")
+       out := "`"
+       for i, line := range lines {
+               out += line
+               if i < len(lines)-1 {
+                       out += "\n"
+               }
+       }
+       out += "`"
+       return out
+}
+
+func add(x, y int) int {
+       return x + y
+}
+
+func mdToHTML(md []byte) []byte {
+       // create markdown parser with extensions
+       extensions := parser.CommonExtensions | parser.AutoHeadingIDs | 
parser.NoEmptyLineBeforeBlock
+       p := parser.NewWithExtensions(extensions)
+       doc := p.Parse(md)
+
+       // create HTML renderer with extensions
+       htmlFlags := html.CommonFlags | html.HrefTargetBlank
+       opts := html.RendererOptions{Flags: htmlFlags}
+       renderer := html.NewRenderer(opts)
+
+       return markdown.Render(doc, renderer)
+}

Reply via email to