You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2023/07/03 03:24:29 UTC

[dubbo-admin] branch refactor-with-go-components updated: Service name mapping (#1146)

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

liujun pushed a commit to branch refactor-with-go-components
in repository https://gitbox.apache.org/repos/asf/dubbo-admin.git


The following commit(s) were added to refs/heads/refactor-with-go-components by this push:
     new 1c32b5e4 Service name mapping (#1146)
1c32b5e4 is described below

commit 1c32b5e4e154c800b7df0f2793c8766d1afd344a
Author: mfordjody <11...@qq.com>
AuthorDate: Mon Jul 3 11:24:25 2023 +0800

    Service name mapping (#1146)
    
    Co-authored-by: Ken Liu <ke...@gmail.com>
---
 cmd/mapping/app/mapping.go                         |  91 ++++++
 cmd/mapping/main.go                                |  31 ++
 .../dubbo.apache.org_servicenamemappings.yaml      |  48 ++++
 pkg/mapping/apis/dubbo.apache.org/v1alpha1/doc.go  |  21 ++
 .../apis/dubbo.apache.org/v1alpha1/register.go     |  47 +++
 pkg/mapping/apis/dubbo.apache.org/v1alpha1/type.go |  49 ++++
 .../v1alpha1/zz_generated.deepcopy.go              | 112 ++++++++
 pkg/mapping/bootstrap/server.go                    |  71 +++++
 pkg/mapping/config/options.go                      |  65 +++++
 pkg/mapping/dubbo/servicenamemapping_server.go     | 282 ++++++++++++++++++
 .../generated/clientset/versioned/clientset.go     | 120 ++++++++
 .../versioned/fake/clientset_generated.go          |  86 ++++++
 .../generated/clientset/versioned/fake/doc.go      |  20 ++
 .../generated/clientset/versioned/fake/register.go |  57 ++++
 .../generated/clientset/versioned/scheme/doc.go    |  20 ++
 .../clientset/versioned/scheme/register.go         |  57 ++++
 .../typed/dubbo.apache.org/v1alpha1/doc.go         |  20 ++
 .../v1alpha1/dubbo.apache.org_client.go            | 107 +++++++
 .../typed/dubbo.apache.org/v1alpha1/fake/doc.go    |  20 ++
 .../v1alpha1/fake/fake_dubbo.apache.org_client.go  |  41 +++
 .../v1alpha1/fake/fake_servicenamemapping.go       | 129 +++++++++
 .../v1alpha1/generated_expansion.go                |  21 ++
 .../v1alpha1/servicenamemapping.go                 | 178 ++++++++++++
 .../externalversions/dubbo.apache.org/interface.go |  46 +++
 .../dubbo.apache.org/v1alpha1/interface.go         |  45 +++
 .../v1alpha1/servicenamemapping.go                 |  90 ++++++
 .../informers/externalversions/factory.go          | 251 ++++++++++++++++
 .../informers/externalversions/generic.go          |  62 ++++
 .../internalinterfaces/factory_interfaces.go       |  40 +++
 .../v1alpha1/expansion_generated.go                |  27 ++
 .../v1alpha1/servicenamemapping.go                 | 100 +++++++
 pkg/mapping/kube/client.go                         | 137 +++++++++
 pkg/mapping/kube/controller.go                     | 155 ++++++++++
 pkg/mapping/model/config.go                        |  32 +++
 pkg/mapping/v1alpha1/servicenamemapping.pb.go      | 154 ++++++++++
 pkg/mapping/v1alpha1/servicenamemapping.proto      |  15 +
 pkg/mapping/v1alpha1/snp.pb.go                     | 315 +++++++++++++++++++++
 pkg/mapping/v1alpha1/snp.proto                     |  35 +++
 pkg/mapping/v1alpha1/snp_grpc.pb.go                | 110 +++++++
 39 files changed, 3307 insertions(+)

diff --git a/cmd/mapping/app/mapping.go b/cmd/mapping/app/mapping.go
new file mode 100644
index 00000000..73319e90
--- /dev/null
+++ b/cmd/mapping/app/mapping.go
@@ -0,0 +1,91 @@
+/*
+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.
+*/
+
+package app
+
+import (
+	"flag"
+	"fmt"
+	"github.com/apache/dubbo-admin/pkg/logger"
+	"github.com/apache/dubbo-admin/pkg/mapping/bootstrap"
+	"github.com/apache/dubbo-admin/pkg/mapping/config"
+	"github.com/spf13/cobra"
+	"github.com/spf13/pflag"
+	"github.com/spf13/viper"
+	"os"
+	"os/signal"
+	"strings"
+	"syscall"
+)
+
+var (
+	replaceWithCamelCase = false
+)
+
+func Flags(cmd *cobra.Command, v *viper.Viper) {
+	cmd.Flags().VisitAll(func(f *pflag.Flag) {
+		configName := f.Name
+		if replaceWithCamelCase {
+			configName = strings.ReplaceAll(f.Name, "-", "")
+		}
+		if !f.Changed && v.IsSet(configName) {
+			val := v.Get(configName)
+			cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val))
+		}
+	})
+}
+
+func initial(cmd *cobra.Command) error {
+	v := viper.New()
+	v.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
+	v.AutomaticEnv()
+	Flags(cmd, v)
+	return nil
+}
+
+func Command() *cobra.Command {
+	options := config.NewOptions()
+	cmd := &cobra.Command{
+		Use: "ServiceMapping",
+		PersistentPreRun: func(cmd *cobra.Command, args []string) {
+			logger.Infof("PreRun Service Mapping")
+			initial(cmd)
+		},
+		Run: func(cmd *cobra.Command, args []string) {
+			logger.Infof("Run Service Mapping %+v", options)
+			if err := Run(options); err != nil {
+				logger.Fatal(err)
+			}
+		},
+	}
+	cmd.Flags().AddGoFlagSet(flag.CommandLine)
+	options.FillFlags(cmd.Flags())
+	return cmd
+}
+
+func Run(option *config.Options) error {
+	s := bootstrap.NewServer(option)
+
+	s.Init()
+	s.Start()
+
+	c := make(chan os.Signal, 1)
+	signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
+	signal.Notify(s.StopChan, syscall.SIGINT, syscall.SIGTERM)
+	<-c
+	return nil
+}
diff --git a/cmd/mapping/main.go b/cmd/mapping/main.go
new file mode 100644
index 00000000..3b652e73
--- /dev/null
+++ b/cmd/mapping/main.go
@@ -0,0 +1,31 @@
+/*
+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.
+*/
+
+package main
+
+import (
+	"github.com/apache/dubbo-admin/cmd/mapping/app"
+	"github.com/apache/dubbo-admin/pkg/logger"
+	"os"
+)
+
+func main() {
+	logger.Init()
+	if err := app.Command().Execute(); err != nil {
+		os.Exit(1)
+	}
+}
diff --git a/deploy/manifests/dubbo.apache.org_servicenamemappings.yaml b/deploy/manifests/dubbo.apache.org_servicenamemappings.yaml
new file mode 100644
index 00000000..b7154fd9
--- /dev/null
+++ b/deploy/manifests/dubbo.apache.org_servicenamemappings.yaml
@@ -0,0 +1,48 @@
+# 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.
+
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  name: servicenamemappings.dubbo.apache.org
+spec:
+  group: dubbo.apache.org
+  versions:
+  - name: v1alpha1
+    served: true
+    storage: true
+    schema:
+      openAPIV3Schema:
+        properties:
+          spec:
+            description:
+              'Spec defines the behavior of a service mapping.
+               https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'
+            properties:
+              applicationNames:
+                items:
+                  type: string 
+                type: array
+              interfaceName:
+                type: string
+            type: object
+        type: object
+  scope: Namespaced
+  names:
+    plural: servicenamemappings
+    singular: servicenamemapping
+    kind: ServiceNameMapping
+    shortNames:
+      - snp
diff --git a/pkg/mapping/apis/dubbo.apache.org/v1alpha1/doc.go b/pkg/mapping/apis/dubbo.apache.org/v1alpha1/doc.go
new file mode 100644
index 00000000..a31823f1
--- /dev/null
+++ b/pkg/mapping/apis/dubbo.apache.org/v1alpha1/doc.go
@@ -0,0 +1,21 @@
+/*
+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.
+*/
+
+// +k8s:deepcopy-gen=package
+// +groupName=dubbo.apache.org
+
+package v1alpha1
diff --git a/pkg/mapping/apis/dubbo.apache.org/v1alpha1/register.go b/pkg/mapping/apis/dubbo.apache.org/v1alpha1/register.go
new file mode 100644
index 00000000..7e565311
--- /dev/null
+++ b/pkg/mapping/apis/dubbo.apache.org/v1alpha1/register.go
@@ -0,0 +1,47 @@
+/*
+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.
+*/
+
+package v1alpha1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+const GroupName = "dubbo.apache.org"
+
+var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
+
+func Resource(resource string) schema.GroupResource {
+	return SchemeGroupVersion.WithResource(resource).GroupResource()
+}
+
+var (
+	SchemeBuilder      = runtime.NewSchemeBuilder(addKnownTypes)
+	localSchemeBuilder = &SchemeBuilder
+	AddToScheme        = localSchemeBuilder.AddToScheme
+)
+
+func addKnownTypes(scheme *runtime.Scheme) error {
+	scheme.AddKnownTypes(SchemeGroupVersion,
+		&ServiceNameMapping{},
+		&ServiceNameMappingList{},
+	)
+	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
+	return nil
+}
diff --git a/pkg/mapping/apis/dubbo.apache.org/v1alpha1/type.go b/pkg/mapping/apis/dubbo.apache.org/v1alpha1/type.go
new file mode 100644
index 00000000..02279b5b
--- /dev/null
+++ b/pkg/mapping/apis/dubbo.apache.org/v1alpha1/type.go
@@ -0,0 +1,49 @@
+/*
+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.
+*/
+
+package v1alpha1
+
+import (
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// +kubetype-gen
+// +kubetype-gen:groupVersion=dubbo.apache.org/v1alpha1
+// +genclient
+// +genclient:noStatus
+// +k8s:deepcopy-gen=true
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type ServiceNameMapping struct {
+	v1.TypeMeta `json:",inline"`
+	// +optional
+	v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
+	// +optional
+	Spec ServiceNameMappingSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
+}
+
+type ServiceNameMappingSpec struct {
+	InterfaceName    string   `json:"interfaceName,omitempty" protobuf:"bytes,1,opt,name=interfaceName,proto3"`
+	ApplicationNames []string `json:"applicationNames,omitempty" protobuf:"bytes,2,rep,name=applicationNames,proto3"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type ServiceNameMappingList struct {
+	v1.TypeMeta `json:",inline"`
+	// +optional
+	v1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
+	Items       []*ServiceNameMapping `json:"items" protobuf:"bytes,2,rep,name=items"`
+}
diff --git a/pkg/mapping/apis/dubbo.apache.org/v1alpha1/zz_generated.deepcopy.go b/pkg/mapping/apis/dubbo.apache.org/v1alpha1/zz_generated.deepcopy.go
new file mode 100644
index 00000000..cad83278
--- /dev/null
+++ b/pkg/mapping/apis/dubbo.apache.org/v1alpha1/zz_generated.deepcopy.go
@@ -0,0 +1,112 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+/*
+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 deepcopy-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ServiceNameMapping) DeepCopyInto(out *ServiceNameMapping) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceNameMapping.
+func (in *ServiceNameMapping) DeepCopy() *ServiceNameMapping {
+	if in == nil {
+		return nil
+	}
+	out := new(ServiceNameMapping)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ServiceNameMapping) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ServiceNameMappingList) DeepCopyInto(out *ServiceNameMappingList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]*ServiceNameMapping, len(*in))
+		for i := range *in {
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(ServiceNameMapping)
+				(*in).DeepCopyInto(*out)
+			}
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceNameMappingList.
+func (in *ServiceNameMappingList) DeepCopy() *ServiceNameMappingList {
+	if in == nil {
+		return nil
+	}
+	out := new(ServiceNameMappingList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ServiceNameMappingList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ServiceNameMappingSpec) DeepCopyInto(out *ServiceNameMappingSpec) {
+	*out = *in
+	if in.ApplicationNames != nil {
+		in, out := &in.ApplicationNames, &out.ApplicationNames
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceNameMappingSpec.
+func (in *ServiceNameMappingSpec) DeepCopy() *ServiceNameMappingSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(ServiceNameMappingSpec)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/pkg/mapping/bootstrap/server.go b/pkg/mapping/bootstrap/server.go
new file mode 100644
index 00000000..80581655
--- /dev/null
+++ b/pkg/mapping/bootstrap/server.go
@@ -0,0 +1,71 @@
+/*
+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.
+*/
+
+package bootstrap
+
+import (
+	"github.com/apache/dubbo-admin/pkg/logger"
+	"github.com/apache/dubbo-admin/pkg/mapping/config"
+	dubbov1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/dubbo"
+	informerV1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/v1alpha1"
+	"github.com/apache/dubbo-admin/pkg/mapping/kube"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/reflection"
+	"os"
+)
+
+type Server struct {
+	StopChan   chan os.Signal
+	Options    *config.Options
+	KubeClient kube.Client
+	snpServer  *dubbov1alpha1.Snp
+	GrpcServer *grpc.Server
+	informer   informerV1alpha1.ServiceNameMappingInformer
+}
+
+func NewServer(options *config.Options) *Server {
+	return &Server{
+		Options:  options,
+		StopChan: make(chan os.Signal, 1),
+	}
+}
+
+func (s *Server) Init() {
+	if s.KubeClient == nil {
+		s.KubeClient = kube.NewClient()
+	}
+	if s.KubeClient != nil {
+		s.snpServer = dubbov1alpha1.NewSnp(s.KubeClient)
+	}
+	if !s.KubeClient.Init(s.Options) {
+		logger.Sugar().Warnf("Failed to connect to Kubernetes cluster. Will ignore OpenID Connect check.")
+		s.Options.IsKubernetesConnected = false
+	} else {
+		s.Options.IsKubernetesConnected = true
+	}
+	logger.Infof("Starting grpc Server")
+	s.GrpcServer = grpc.NewServer()
+	logger.Infof("Started grpc Server")
+	reflection.Register(s.GrpcServer)
+	logger.Infof("Service Mapping grpc Server")
+	s.snpServer.Register(s.GrpcServer)
+}
+
+func (s *Server) Start() {
+	s.KubeClient.InitContainer()
+	logger.Sugar().Infof("Server started.")
+}
diff --git a/pkg/mapping/config/options.go b/pkg/mapping/config/options.go
new file mode 100644
index 00000000..0afdef1e
--- /dev/null
+++ b/pkg/mapping/config/options.go
@@ -0,0 +1,65 @@
+/*
+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.
+*/
+
+package config
+
+import (
+	"crypto/rand"
+	"encoding/base32"
+	"fmt"
+	"github.com/spf13/pflag"
+	"os"
+)
+
+type Options struct {
+	IsKubernetesConnected bool
+	ResourceIdentity      string
+}
+
+func NewOptions() *Options {
+	return &Options{
+		IsKubernetesConnected: false,
+		ResourceIdentity:      GetStringEnv("POD_NAME", GetDefaultResourceIdentity()),
+	}
+}
+
+func (o *Options) FillFlags(flags *pflag.FlagSet) {
+	flags.BoolVar(&o.IsKubernetesConnected, "is-kubernetes-connected", false, "dubbo connected with kubernetes")
+}
+
+func GetStringEnv(name string, def string) string {
+	val, ex := os.LookupEnv(name)
+	if ex {
+		return val
+	} else {
+		return def
+	}
+}
+
+func GetDefaultResourceIdentity() string {
+	hostname, err := os.Hostname()
+	if err != nil {
+		return ""
+	}
+	randomBytes := make([]byte, 5)
+	_, err = rand.Read(randomBytes)
+	if err != nil {
+		return ""
+	}
+	randomStr := base32.StdEncoding.EncodeToString(randomBytes)
+	return fmt.Sprintf("%s-%s", hostname, randomStr)
+}
diff --git a/pkg/mapping/dubbo/servicenamemapping_server.go b/pkg/mapping/dubbo/servicenamemapping_server.go
new file mode 100644
index 00000000..e2738a00
--- /dev/null
+++ b/pkg/mapping/dubbo/servicenamemapping_server.go
@@ -0,0 +1,282 @@
+/*
+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.
+*/
+
+package v1alpha1
+
+import (
+	"context"
+	"fmt"
+	"github.com/dubbogo/gost/log/logger"
+	"strings"
+	"time"
+)
+
+import (
+	apisv1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+	"github.com/apache/dubbo-admin/pkg/mapping/kube"
+	"github.com/apache/dubbo-admin/pkg/mapping/model"
+	dubbov1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/v1alpha1"
+	"github.com/pkg/errors"
+	"google.golang.org/grpc"
+	apierror "k8s.io/apimachinery/pkg/api/errors"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+type Snp struct {
+	dubbov1alpha1.UnimplementedServiceNameMappingServiceServer
+
+	KubeClient     kube.Client
+	queue          chan *RegisterRequest
+	debounceAfter  time.Duration
+	debounceMax    time.Duration
+	enableDebounce bool
+}
+
+func NewSnp(kubeClient kube.Client) *Snp {
+	return &Snp{
+		KubeClient: kubeClient,
+		queue:      make(chan *RegisterRequest, 10),
+	}
+}
+
+func (s *Snp) RegisterServiceAppMapping(ctx context.Context, req *dubbov1alpha1.ServiceMappingRequest) (*dubbov1alpha1.ServiceMappingResponse, error) {
+	namespace := req.GetNamespace()
+	interfaces := req.GetInterfaceNames()
+	applicationName := req.GetApplicationName()
+
+	registerReq := &RegisterRequest{ConfigsUpdated: map[model.ConfigKey]map[string]struct{}{}}
+	for _, interfaceName := range interfaces {
+		key := model.ConfigKey{
+			Name:      interfaceName,
+			Namespace: namespace,
+		}
+		if _, ok := registerReq.ConfigsUpdated[key]; !ok {
+			registerReq.ConfigsUpdated[key] = make(map[string]struct{})
+		}
+		registerReq.ConfigsUpdated[key][applicationName] = struct{}{}
+	}
+	s.queue <- registerReq
+
+	return &dubbov1alpha1.ServiceMappingResponse{}, nil
+}
+
+func (s *Snp) Register(server *grpc.Server) {
+	dubbov1alpha1.RegisterServiceNameMappingServiceServer(server, s)
+}
+
+func (s *Snp) Start(stop <-chan struct{}) {
+	if s == nil {
+		logger.Warn("Snp server is not init, skip start")
+		return
+	}
+	go s.debounce(stop, s.push)
+}
+
+func (s *Snp) push(req *RegisterRequest) {
+	for key, m := range req.ConfigsUpdated {
+		var appNames []string
+		for app := range m {
+			appNames = append(appNames, app)
+		}
+		for i := 0; i < 3; i++ {
+			if err := tryRegister(s.KubeClient, key.Namespace, key.Name, appNames); err != nil {
+				logger.Errorf(" register [%v] failed: %v, try again later", key, err)
+			} else {
+				break
+			}
+		}
+	}
+}
+
+func (s *Snp) debounce(stopCh <-chan struct{}, pushFn func(req *RegisterRequest)) {
+	ch := s.queue
+	var timeChan <-chan time.Time
+	var startDebounce time.Time
+	var lastConfigUpdateTime time.Time
+
+	pushCounter := 0
+	debouncedEvents := 0
+
+	var req *RegisterRequest
+
+	free := true
+	freeCh := make(chan struct{}, 1)
+
+	push := func(req *RegisterRequest) {
+		pushFn(req)
+		freeCh <- struct{}{}
+	}
+
+	pushWorker := func() {
+		eventDelay := time.Since(startDebounce)
+		quietTime := time.Since(lastConfigUpdateTime)
+		if eventDelay >= s.debounceMax || quietTime >= s.debounceAfter {
+			if req != nil {
+				pushCounter++
+
+				if req.ConfigsUpdated != nil {
+					logger.Infof(" Push debounce stable[%d] %d for config %s: %v since last change, %v since last push",
+						pushCounter, debouncedEvents, configsUpdated(req),
+						quietTime, eventDelay)
+				}
+				free = false
+				go push(req)
+				req = nil
+				debouncedEvents = 0
+			}
+		} else {
+			timeChan = time.After(s.debounceAfter - quietTime)
+		}
+	}
+
+	for {
+		select {
+		case <-freeCh:
+			free = true
+			pushWorker()
+		case r := <-ch:
+			if !s.enableDebounce {
+				go push(r)
+				req = nil
+				continue
+			}
+
+			lastConfigUpdateTime = time.Now()
+			if debouncedEvents == 0 {
+				timeChan = time.After(200 * time.Millisecond)
+				startDebounce = lastConfigUpdateTime
+			}
+			debouncedEvents++
+
+			req = req.Merge(r)
+		case <-timeChan:
+			if free {
+				pushWorker()
+			}
+		case <-stopCh:
+			return
+		}
+	}
+}
+
+func getOrCreateSnp(kubeClient kube.Client, namespace string, interfaceName string, newApps []string) (*apisv1alpha1.ServiceNameMapping, bool, error) {
+	ctx := context.TODO()
+	lowerCaseName := strings.ToLower(strings.ReplaceAll(interfaceName, ".", "-"))
+	snpInterface := kubeClient.Admin().DubboV1alpha1().ServiceNameMappings(namespace)
+	snp, err := snpInterface.Get(ctx, lowerCaseName, v1.GetOptions{})
+	if err != nil {
+		if apierror.IsNotFound(err) {
+			snp, err = snpInterface.Create(ctx, &apisv1alpha1.ServiceNameMapping{
+				ObjectMeta: v1.ObjectMeta{
+					Name:      lowerCaseName,
+					Namespace: namespace,
+					Labels: map[string]string{
+						"interface": interfaceName,
+					},
+				},
+				Spec: apisv1alpha1.ServiceNameMappingSpec{
+					InterfaceName:    interfaceName,
+					ApplicationNames: newApps,
+				},
+			}, v1.CreateOptions{})
+			if err == nil {
+				logger.Debugf("create snp %s revision %s", interfaceName, snp.ResourceVersion)
+				return snp, true, nil
+			}
+			if apierror.IsAlreadyExists(err) {
+				logger.Debugf("[%s] has been exists, err: %v", err)
+				snp, err = snpInterface.Get(ctx, lowerCaseName, v1.GetOptions{})
+				if err != nil {
+					return nil, false, errors.Wrap(err, "tryRegister retry get snp error")
+				}
+			}
+		} else {
+			return nil, false, errors.Wrap(err, "tryRegister get snp error")
+		}
+	}
+	return snp, false, nil
+}
+
+func tryRegister(kubeClient kube.Client, namespace, interfaceName string, newApps []string) error {
+	logger.Debugf("try register [%s] in namespace [%s] with [%v] apps", interfaceName, namespace, len(newApps))
+	snp, created, err := getOrCreateSnp(kubeClient, namespace, interfaceName, newApps)
+	if created {
+		logger.Debugf("register success, revision:%s", snp.ResourceVersion)
+		return nil
+	}
+	if err != nil {
+		return err
+	}
+
+	previousLen := len(snp.Spec.ApplicationNames)
+	previousAppNames := make(map[string]struct{}, previousLen)
+	for _, name := range snp.Spec.ApplicationNames {
+		previousAppNames[name] = struct{}{}
+	}
+	for _, newApp := range newApps {
+		previousAppNames[newApp] = struct{}{}
+	}
+	if len(previousAppNames) == previousLen {
+		logger.Debugf("[%s] has been registered: %v", interfaceName, newApps)
+		return nil
+	}
+
+	mergedApps := make([]string, 0, len(previousAppNames))
+	for name := range previousAppNames {
+		mergedApps = append(mergedApps, name)
+	}
+	snp.Spec.ApplicationNames = mergedApps
+	snpInterface := kubeClient.Admin().DubboV1alpha1().ServiceNameMappings(namespace)
+	snp, err = snpInterface.Update(context.Background(), snp, v1.UpdateOptions{})
+	if err != nil {
+		return errors.Wrap(err, " update failed")
+	}
+	logger.Debugf("register update success, revision:%s", snp.ResourceVersion)
+	return nil
+}
+
+type RegisterRequest struct {
+	ConfigsUpdated map[model.ConfigKey]map[string]struct{}
+}
+
+func (r *RegisterRequest) Merge(req *RegisterRequest) *RegisterRequest {
+	if r == nil {
+		return req
+	}
+	for key, newApps := range req.ConfigsUpdated {
+		if _, ok := r.ConfigsUpdated[key]; !ok {
+			r.ConfigsUpdated[key] = make(map[string]struct{})
+		}
+		for app, _ := range newApps {
+			r.ConfigsUpdated[key][app] = struct{}{}
+		}
+	}
+	return r
+}
+
+func configsUpdated(req *RegisterRequest) string {
+	configs := ""
+	for key := range req.ConfigsUpdated {
+		configs += key.Name + key.Namespace
+		break
+	}
+	if len(req.ConfigsUpdated) > 1 {
+		more := fmt.Sprintf(" and %d more configs", len(req.ConfigsUpdated)-1)
+		configs += more
+	}
+	return configs
+}
diff --git a/pkg/mapping/generated/clientset/versioned/clientset.go b/pkg/mapping/generated/clientset/versioned/clientset.go
new file mode 100644
index 00000000..808b4199
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/clientset.go
@@ -0,0 +1,120 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package versioned
+
+import (
+	"fmt"
+	dubbov1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1"
+	"net/http"
+
+	discovery "k8s.io/client-go/discovery"
+	rest "k8s.io/client-go/rest"
+	flowcontrol "k8s.io/client-go/util/flowcontrol"
+)
+
+type Interface interface {
+	Discovery() discovery.DiscoveryInterface
+	DubboV1alpha1() dubbov1alpha1.DubboV1alpha1Interface
+}
+
+// Clientset contains the clients for groups.
+type Clientset struct {
+	*discovery.DiscoveryClient
+	dubboV1alpha1 *dubbov1alpha1.DubboV1alpha1Client
+}
+
+// DubboV1alpha1 retrieves the DubboV1alpha1Client
+func (c *Clientset) DubboV1alpha1() dubbov1alpha1.DubboV1alpha1Interface {
+	return c.dubboV1alpha1
+}
+
+// Discovery retrieves the DiscoveryClient
+func (c *Clientset) Discovery() discovery.DiscoveryInterface {
+	if c == nil {
+		return nil
+	}
+	return c.DiscoveryClient
+}
+
+// NewForConfig creates a new Clientset for the given config.
+// If config's RateLimiter is not set and QPS and Burst are acceptable,
+// NewForConfig will generate a rate-limiter in configShallowCopy.
+// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
+// where httpClient was generated with rest.HTTPClientFor(c).
+func NewForConfig(c *rest.Config) (*Clientset, error) {
+	configShallowCopy := *c
+
+	if configShallowCopy.UserAgent == "" {
+		configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
+	}
+
+	// share the transport between all clients
+	httpClient, err := rest.HTTPClientFor(&configShallowCopy)
+	if err != nil {
+		return nil, err
+	}
+
+	return NewForConfigAndClient(&configShallowCopy, httpClient)
+}
+
+// NewForConfigAndClient creates a new Clientset for the given config and http client.
+// Note the http client provided takes precedence over the configured transport values.
+// If config's RateLimiter is not set and QPS and Burst are acceptable,
+// NewForConfigAndClient will generate a rate-limiter in configShallowCopy.
+func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) {
+	configShallowCopy := *c
+	if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
+		if configShallowCopy.Burst <= 0 {
+			return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
+		}
+		configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
+	}
+
+	var cs Clientset
+	var err error
+	cs.dubboV1alpha1, err = dubbov1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
+	if err != nil {
+		return nil, err
+	}
+
+	cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient)
+	if err != nil {
+		return nil, err
+	}
+	return &cs, nil
+}
+
+// NewForConfigOrDie creates a new Clientset for the given config and
+// panics if there is an error in the config.
+func NewForConfigOrDie(c *rest.Config) *Clientset {
+	cs, err := NewForConfig(c)
+	if err != nil {
+		panic(err)
+	}
+	return cs
+}
+
+// New creates a new Clientset for the given RESTClient.
+func New(c rest.Interface) *Clientset {
+	var cs Clientset
+	cs.dubboV1alpha1 = dubbov1alpha1.New(c)
+
+	cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
+	return &cs
+}
diff --git a/pkg/mapping/generated/clientset/versioned/fake/clientset_generated.go b/pkg/mapping/generated/clientset/versioned/fake/clientset_generated.go
new file mode 100644
index 00000000..3e11b2c4
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/fake/clientset_generated.go
@@ -0,0 +1,86 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	clientset "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned"
+	dubbov1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1"
+	fakedubbov1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake"
+
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/watch"
+	"k8s.io/client-go/discovery"
+	fakediscovery "k8s.io/client-go/discovery/fake"
+	"k8s.io/client-go/testing"
+)
+
+// NewSimpleClientset returns a clientset that will respond with the provided objects.
+// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
+// without applying any validations and/or defaults. It shouldn't be considered a replacement
+// for a real clientset and is mostly useful in simple unit tests.
+func NewSimpleClientset(objects ...runtime.Object) *Clientset {
+	o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
+	for _, obj := range objects {
+		if err := o.Add(obj); err != nil {
+			panic(err)
+		}
+	}
+
+	cs := &Clientset{tracker: o}
+	cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
+	cs.AddReactor("*", "*", testing.ObjectReaction(o))
+	cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
+		gvr := action.GetResource()
+		ns := action.GetNamespace()
+		watch, err := o.Watch(gvr, ns)
+		if err != nil {
+			return false, nil, err
+		}
+		return true, watch, nil
+	})
+
+	return cs
+}
+
+// Clientset implements clientset.Interface. Meant to be embedded into a
+// struct to get a default implementation. This makes faking out just the method
+// you want to test easier.
+type Clientset struct {
+	testing.Fake
+	discovery *fakediscovery.FakeDiscovery
+	tracker   testing.ObjectTracker
+}
+
+func (c *Clientset) Discovery() discovery.DiscoveryInterface {
+	return c.discovery
+}
+
+func (c *Clientset) Tracker() testing.ObjectTracker {
+	return c.tracker
+}
+
+var (
+	_ clientset.Interface = &Clientset{}
+	_ testing.FakeClient  = &Clientset{}
+)
+
+// DubboV1alpha1 retrieves the DubboV1alpha1Client
+func (c *Clientset) DubboV1alpha1() dubbov1alpha1.DubboV1alpha1Interface {
+	return &fakedubbov1alpha1.FakeDubboV1alpha1{Fake: &c.Fake}
+}
diff --git a/pkg/mapping/generated/clientset/versioned/fake/doc.go b/pkg/mapping/generated/clientset/versioned/fake/doc.go
new file mode 100644
index 00000000..9b99e716
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated fake clientset.
+package fake
diff --git a/pkg/mapping/generated/clientset/versioned/fake/register.go b/pkg/mapping/generated/clientset/versioned/fake/register.go
new file mode 100644
index 00000000..0d54b078
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/fake/register.go
@@ -0,0 +1,57 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	dubbov1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	serializer "k8s.io/apimachinery/pkg/runtime/serializer"
+	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
+)
+
+var scheme = runtime.NewScheme()
+var codecs = serializer.NewCodecFactory(scheme)
+
+var localSchemeBuilder = runtime.SchemeBuilder{
+	dubbov1alpha1.AddToScheme,
+}
+
+// AddToScheme adds all types of this clientset into the given scheme. This allows composition
+// of clientsets, like in:
+//
+//	import (
+//	  "k8s.io/client-go/kubernetes"
+//	  clientsetscheme "k8s.io/client-go/kubernetes/scheme"
+//	  aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
+//	)
+//
+//	kclientset, _ := kubernetes.NewForConfig(c)
+//	_ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
+//
+// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
+// correctly.
+var AddToScheme = localSchemeBuilder.AddToScheme
+
+func init() {
+	v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
+	utilruntime.Must(AddToScheme(scheme))
+}
diff --git a/pkg/mapping/generated/clientset/versioned/scheme/doc.go b/pkg/mapping/generated/clientset/versioned/scheme/doc.go
new file mode 100644
index 00000000..7dc37561
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/scheme/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package contains the scheme of the automatically generated clientset.
+package scheme
diff --git a/pkg/mapping/generated/clientset/versioned/scheme/register.go b/pkg/mapping/generated/clientset/versioned/scheme/register.go
new file mode 100644
index 00000000..6df5ebc6
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/scheme/register.go
@@ -0,0 +1,57 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package scheme
+
+import (
+	dubbov1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	serializer "k8s.io/apimachinery/pkg/runtime/serializer"
+	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
+)
+
+var Scheme = runtime.NewScheme()
+var Codecs = serializer.NewCodecFactory(Scheme)
+var ParameterCodec = runtime.NewParameterCodec(Scheme)
+var localSchemeBuilder = runtime.SchemeBuilder{
+	dubbov1alpha1.AddToScheme,
+}
+
+// AddToScheme adds all types of this clientset into the given scheme. This allows composition
+// of clientsets, like in:
+//
+//	import (
+//	  "k8s.io/client-go/kubernetes"
+//	  clientsetscheme "k8s.io/client-go/kubernetes/scheme"
+//	  aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
+//	)
+//
+//	kclientset, _ := kubernetes.NewForConfig(c)
+//	_ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
+//
+// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
+// correctly.
+var AddToScheme = localSchemeBuilder.AddToScheme
+
+func init() {
+	v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
+	utilruntime.Must(AddToScheme(Scheme))
+}
diff --git a/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/doc.go b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/doc.go
new file mode 100644
index 00000000..df51baa4
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated typed clients.
+package v1alpha1
diff --git a/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/dubbo.apache.org_client.go b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/dubbo.apache.org_client.go
new file mode 100644
index 00000000..17b50d19
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/dubbo.apache.org_client.go
@@ -0,0 +1,107 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	v1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+	"github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned/scheme"
+	"net/http"
+
+	rest "k8s.io/client-go/rest"
+)
+
+type DubboV1alpha1Interface interface {
+	RESTClient() rest.Interface
+	ServiceNameMappingsGetter
+}
+
+// DubboV1alpha1Client is used to interact with features provided by the dubbo.apache.org group.
+type DubboV1alpha1Client struct {
+	restClient rest.Interface
+}
+
+func (c *DubboV1alpha1Client) ServiceNameMappings(namespace string) ServiceNameMappingInterface {
+	return newServiceNameMappings(c, namespace)
+}
+
+// NewForConfig creates a new DubboV1alpha1Client for the given config.
+// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
+// where httpClient was generated with rest.HTTPClientFor(c).
+func NewForConfig(c *rest.Config) (*DubboV1alpha1Client, error) {
+	config := *c
+	if err := setConfigDefaults(&config); err != nil {
+		return nil, err
+	}
+	httpClient, err := rest.HTTPClientFor(&config)
+	if err != nil {
+		return nil, err
+	}
+	return NewForConfigAndClient(&config, httpClient)
+}
+
+// NewForConfigAndClient creates a new DubboV1alpha1Client for the given config and http client.
+// Note the http client provided takes precedence over the configured transport values.
+func NewForConfigAndClient(c *rest.Config, h *http.Client) (*DubboV1alpha1Client, error) {
+	config := *c
+	if err := setConfigDefaults(&config); err != nil {
+		return nil, err
+	}
+	client, err := rest.RESTClientForConfigAndClient(&config, h)
+	if err != nil {
+		return nil, err
+	}
+	return &DubboV1alpha1Client{client}, nil
+}
+
+// NewForConfigOrDie creates a new DubboV1alpha1Client for the given config and
+// panics if there is an error in the config.
+func NewForConfigOrDie(c *rest.Config) *DubboV1alpha1Client {
+	client, err := NewForConfig(c)
+	if err != nil {
+		panic(err)
+	}
+	return client
+}
+
+// New creates a new DubboV1alpha1Client for the given RESTClient.
+func New(c rest.Interface) *DubboV1alpha1Client {
+	return &DubboV1alpha1Client{c}
+}
+
+func setConfigDefaults(config *rest.Config) error {
+	gv := v1alpha1.SchemeGroupVersion
+	config.GroupVersion = &gv
+	config.APIPath = "/apis"
+	config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
+
+	if config.UserAgent == "" {
+		config.UserAgent = rest.DefaultKubernetesUserAgent()
+	}
+
+	return nil
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *DubboV1alpha1Client) RESTClient() rest.Interface {
+	if c == nil {
+		return nil
+	}
+	return c.restClient
+}
diff --git a/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake/doc.go b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake/doc.go
new file mode 100644
index 00000000..16f44399
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake/fake_dubbo.apache.org_client.go b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake/fake_dubbo.apache.org_client.go
new file mode 100644
index 00000000..2ab51be9
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake/fake_dubbo.apache.org_client.go
@@ -0,0 +1,41 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	v1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1"
+
+	rest "k8s.io/client-go/rest"
+	testing "k8s.io/client-go/testing"
+)
+
+type FakeDubboV1alpha1 struct {
+	*testing.Fake
+}
+
+func (c *FakeDubboV1alpha1) ServiceNameMappings(namespace string) v1alpha1.ServiceNameMappingInterface {
+	return &FakeServiceNameMappings{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeDubboV1alpha1) RESTClient() rest.Interface {
+	var ret *rest.RESTClient
+	return ret
+}
diff --git a/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake/fake_servicenamemapping.go b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake/fake_servicenamemapping.go
new file mode 100644
index 00000000..cddb67f2
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/fake/fake_servicenamemapping.go
@@ -0,0 +1,129 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+	v1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeServiceNameMappings implements ServiceNameMappingInterface
+type FakeServiceNameMappings struct {
+	Fake *FakeDubboV1alpha1
+	ns   string
+}
+
+var servicenamemappingsResource = v1alpha1.SchemeGroupVersion.WithResource("servicenamemappings")
+
+var servicenamemappingsKind = v1alpha1.SchemeGroupVersion.WithKind("ServiceNameMapping")
+
+// Get takes name of the serviceNameMapping, and returns the corresponding serviceNameMapping object, and an error if there is any.
+func (c *FakeServiceNameMappings) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ServiceNameMapping, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetAction(servicenamemappingsResource, c.ns, name), &v1alpha1.ServiceNameMapping{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceNameMapping), err
+}
+
+// List takes label and field selectors, and returns the list of ServiceNameMappings that match those selectors.
+func (c *FakeServiceNameMappings) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ServiceNameMappingList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewListAction(servicenamemappingsResource, servicenamemappingsKind, c.ns, opts), &v1alpha1.ServiceNameMappingList{})
+
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v1alpha1.ServiceNameMappingList{ListMeta: obj.(*v1alpha1.ServiceNameMappingList).ListMeta}
+	for _, item := range obj.(*v1alpha1.ServiceNameMappingList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested serviceNameMappings.
+func (c *FakeServiceNameMappings) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewWatchAction(servicenamemappingsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a serviceNameMapping and creates it.  Returns the server's representation of the serviceNameMapping, and an error, if there is any.
+func (c *FakeServiceNameMappings) Create(ctx context.Context, serviceNameMapping *v1alpha1.ServiceNameMapping, opts v1.CreateOptions) (result *v1alpha1.ServiceNameMapping, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewCreateAction(servicenamemappingsResource, c.ns, serviceNameMapping), &v1alpha1.ServiceNameMapping{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceNameMapping), err
+}
+
+// Update takes the representation of a serviceNameMapping and updates it. Returns the server's representation of the serviceNameMapping, and an error, if there is any.
+func (c *FakeServiceNameMappings) Update(ctx context.Context, serviceNameMapping *v1alpha1.ServiceNameMapping, opts v1.UpdateOptions) (result *v1alpha1.ServiceNameMapping, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateAction(servicenamemappingsResource, c.ns, serviceNameMapping), &v1alpha1.ServiceNameMapping{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceNameMapping), err
+}
+
+// Delete takes name of the serviceNameMapping and deletes it. Returns an error if one occurs.
+func (c *FakeServiceNameMappings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewDeleteActionWithOptions(servicenamemappingsResource, c.ns, name, opts), &v1alpha1.ServiceNameMapping{})
+
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeServiceNameMappings) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	action := testing.NewDeleteCollectionAction(servicenamemappingsResource, c.ns, listOpts)
+
+	_, err := c.Fake.Invokes(action, &v1alpha1.ServiceNameMappingList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched serviceNameMapping.
+func (c *FakeServiceNameMappings) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ServiceNameMapping, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewPatchSubresourceAction(servicenamemappingsResource, c.ns, name, pt, data, subresources...), &v1alpha1.ServiceNameMapping{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceNameMapping), err
+}
diff --git a/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/generated_expansion.go b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/generated_expansion.go
new file mode 100644
index 00000000..09ac4658
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/generated_expansion.go
@@ -0,0 +1,21 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+type ServiceNameMappingExpansion interface{}
diff --git a/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/servicenamemapping.go b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/servicenamemapping.go
new file mode 100644
index 00000000..e13dbff7
--- /dev/null
+++ b/pkg/mapping/generated/clientset/versioned/typed/dubbo.apache.org/v1alpha1/servicenamemapping.go
@@ -0,0 +1,178 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"context"
+	v1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+	scheme "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned/scheme"
+	"time"
+
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// ServiceNameMappingsGetter has a method to return a ServiceNameMappingInterface.
+// A group's client should implement this interface.
+type ServiceNameMappingsGetter interface {
+	ServiceNameMappings(namespace string) ServiceNameMappingInterface
+}
+
+// ServiceNameMappingInterface has methods to work with ServiceNameMapping resources.
+type ServiceNameMappingInterface interface {
+	Create(ctx context.Context, serviceNameMapping *v1alpha1.ServiceNameMapping, opts v1.CreateOptions) (*v1alpha1.ServiceNameMapping, error)
+	Update(ctx context.Context, serviceNameMapping *v1alpha1.ServiceNameMapping, opts v1.UpdateOptions) (*v1alpha1.ServiceNameMapping, error)
+	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ServiceNameMapping, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ServiceNameMappingList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ServiceNameMapping, err error)
+	ServiceNameMappingExpansion
+}
+
+// serviceNameMappings implements ServiceNameMappingInterface
+type serviceNameMappings struct {
+	client rest.Interface
+	ns     string
+}
+
+// newServiceNameMappings returns a ServiceNameMappings
+func newServiceNameMappings(c *DubboV1alpha1Client, namespace string) *serviceNameMappings {
+	return &serviceNameMappings{
+		client: c.RESTClient(),
+		ns:     namespace,
+	}
+}
+
+// Get takes name of the serviceNameMapping, and returns the corresponding serviceNameMapping object, and an error if there is any.
+func (c *serviceNameMappings) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ServiceNameMapping, err error) {
+	result = &v1alpha1.ServiceNameMapping{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("servicenamemappings").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of ServiceNameMappings that match those selectors.
+func (c *serviceNameMappings) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ServiceNameMappingList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v1alpha1.ServiceNameMappingList{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("servicenamemappings").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested serviceNameMappings.
+func (c *serviceNameMappings) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Namespace(c.ns).
+		Resource("servicenamemappings").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
+
+// Create takes the representation of a serviceNameMapping and creates it.  Returns the server's representation of the serviceNameMapping, and an error, if there is any.
+func (c *serviceNameMappings) Create(ctx context.Context, serviceNameMapping *v1alpha1.ServiceNameMapping, opts v1.CreateOptions) (result *v1alpha1.ServiceNameMapping, err error) {
+	result = &v1alpha1.ServiceNameMapping{}
+	err = c.client.Post().
+		Namespace(c.ns).
+		Resource("servicenamemappings").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(serviceNameMapping).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Update takes the representation of a serviceNameMapping and updates it. Returns the server's representation of the serviceNameMapping, and an error, if there is any.
+func (c *serviceNameMappings) Update(ctx context.Context, serviceNameMapping *v1alpha1.ServiceNameMapping, opts v1.UpdateOptions) (result *v1alpha1.ServiceNameMapping, err error) {
+	result = &v1alpha1.ServiceNameMapping{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("servicenamemappings").
+		Name(serviceNameMapping.Name).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(serviceNameMapping).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Delete takes name of the serviceNameMapping and deletes it. Returns an error if one occurs.
+func (c *serviceNameMappings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("servicenamemappings").
+		Name(name).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *serviceNameMappings) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	var timeout time.Duration
+	if listOpts.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("servicenamemappings").
+		VersionedParams(&listOpts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// Patch applies the patch and returns the patched serviceNameMapping.
+func (c *serviceNameMappings) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ServiceNameMapping, err error) {
+	result = &v1alpha1.ServiceNameMapping{}
+	err = c.client.Patch(pt).
+		Namespace(c.ns).
+		Resource("servicenamemappings").
+		Name(name).
+		SubResource(subresources...).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(data).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/interface.go b/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/interface.go
new file mode 100644
index 00000000..777d2e3b
--- /dev/null
+++ b/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/interface.go
@@ -0,0 +1,46 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package dubbo
+
+import (
+	v1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/v1alpha1"
+	internalinterfaces "github.com/apache/dubbo-admin/pkg/mapping/generated/informers/externalversions/internalinterfaces"
+)
+
+// Interface provides access to each of this group's versions.
+type Interface interface {
+	// V1alpha1 provides access to shared informers for resources in V1alpha1.
+	V1alpha1() v1alpha1.Interface
+}
+
+type group struct {
+	factory          internalinterfaces.SharedInformerFactory
+	namespace        string
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+}
+
+// New returns a new Interface.
+func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
+	return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
+}
+
+// V1alpha1 returns a new v1alpha1.Interface.
+func (g *group) V1alpha1() v1alpha1.Interface {
+	return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
+}
diff --git a/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/v1alpha1/interface.go b/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/v1alpha1/interface.go
new file mode 100644
index 00000000..f894ad11
--- /dev/null
+++ b/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/v1alpha1/interface.go
@@ -0,0 +1,45 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	internalinterfaces "github.com/apache/dubbo-admin/pkg/mapping/generated/informers/externalversions/internalinterfaces"
+)
+
+// Interface provides access to all the informers in this group version.
+type Interface interface {
+	// ServiceNameMappings returns a ServiceNameMappingInformer.
+	ServiceNameMappings() ServiceNameMappingInformer
+}
+
+type version struct {
+	factory          internalinterfaces.SharedInformerFactory
+	namespace        string
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+}
+
+// New returns a new Interface.
+func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
+	return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
+}
+
+// ServiceNameMappings returns a ServiceNameMappingInformer.
+func (v *version) ServiceNameMappings() ServiceNameMappingInformer {
+	return &serviceNameMappingInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
diff --git a/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/v1alpha1/servicenamemapping.go b/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/v1alpha1/servicenamemapping.go
new file mode 100644
index 00000000..b9ae228e
--- /dev/null
+++ b/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/v1alpha1/servicenamemapping.go
@@ -0,0 +1,90 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"context"
+	dubboapacheorgv1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+	versioned "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned"
+	internalinterfaces "github.com/apache/dubbo-admin/pkg/mapping/generated/informers/externalversions/internalinterfaces"
+	v1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/generated/listers/dubbo.apache.org/v1alpha1"
+	time "time"
+
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// ServiceNameMappingInformer provides access to a shared informer and lister for
+// ServiceNameMappings.
+type ServiceNameMappingInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v1alpha1.ServiceNameMappingLister
+}
+
+type serviceNameMappingInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	namespace        string
+}
+
+// NewServiceNameMappingInformer constructs a new informer for ServiceNameMapping type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewServiceNameMappingInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredServiceNameMappingInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredServiceNameMappingInformer constructs a new informer for ServiceNameMapping type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredServiceNameMappingInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.DubboV1alpha1().ServiceNameMappings(namespace).List(context.TODO(), options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.DubboV1alpha1().ServiceNameMappings(namespace).Watch(context.TODO(), options)
+			},
+		},
+		&dubboapacheorgv1alpha1.ServiceNameMapping{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *serviceNameMappingInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredServiceNameMappingInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *serviceNameMappingInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&dubboapacheorgv1alpha1.ServiceNameMapping{}, f.defaultInformer)
+}
+
+func (f *serviceNameMappingInformer) Lister() v1alpha1.ServiceNameMappingLister {
+	return v1alpha1.NewServiceNameMappingLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/mapping/generated/informers/externalversions/factory.go b/pkg/mapping/generated/informers/externalversions/factory.go
new file mode 100644
index 00000000..0c949776
--- /dev/null
+++ b/pkg/mapping/generated/informers/externalversions/factory.go
@@ -0,0 +1,251 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package externalversions
+
+import (
+	versioned "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned"
+	dubboapacheorg "github.com/apache/dubbo-admin/pkg/mapping/generated/informers/externalversions/dubbo.apache.org"
+	internalinterfaces "github.com/apache/dubbo-admin/pkg/mapping/generated/informers/externalversions/internalinterfaces"
+	reflect "reflect"
+	sync "sync"
+	time "time"
+
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// SharedInformerOption defines the functional option type for SharedInformerFactory.
+type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
+
+type sharedInformerFactory struct {
+	client           versioned.Interface
+	namespace        string
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	lock             sync.Mutex
+	defaultResync    time.Duration
+	customResync     map[reflect.Type]time.Duration
+
+	informers map[reflect.Type]cache.SharedIndexInformer
+	// startedInformers is used for tracking which informers have been started.
+	// This allows Start() to be called multiple times safely.
+	startedInformers map[reflect.Type]bool
+	// wg tracks how many goroutines were started.
+	wg sync.WaitGroup
+	// shuttingDown is true when Shutdown has been called. It may still be running
+	// because it needs to wait for goroutines.
+	shuttingDown bool
+}
+
+// WithCustomResyncConfig sets a custom resync period for the specified informer types.
+func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
+	return func(factory *sharedInformerFactory) *sharedInformerFactory {
+		for k, v := range resyncConfig {
+			factory.customResync[reflect.TypeOf(k)] = v
+		}
+		return factory
+	}
+}
+
+// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
+func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
+	return func(factory *sharedInformerFactory) *sharedInformerFactory {
+		factory.tweakListOptions = tweakListOptions
+		return factory
+	}
+}
+
+// WithNamespace limits the SharedInformerFactory to the specified namespace.
+func WithNamespace(namespace string) SharedInformerOption {
+	return func(factory *sharedInformerFactory) *sharedInformerFactory {
+		factory.namespace = namespace
+		return factory
+	}
+}
+
+// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
+func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
+	return NewSharedInformerFactoryWithOptions(client, defaultResync)
+}
+
+// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
+// Listers obtained via this SharedInformerFactory will be subject to the same filters
+// as specified here.
+// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
+func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
+	return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
+}
+
+// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
+func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
+	factory := &sharedInformerFactory{
+		client:           client,
+		namespace:        v1.NamespaceAll,
+		defaultResync:    defaultResync,
+		informers:        make(map[reflect.Type]cache.SharedIndexInformer),
+		startedInformers: make(map[reflect.Type]bool),
+		customResync:     make(map[reflect.Type]time.Duration),
+	}
+
+	// Apply all options
+	for _, opt := range options {
+		factory = opt(factory)
+	}
+
+	return factory
+}
+
+func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
+	f.lock.Lock()
+	defer f.lock.Unlock()
+
+	if f.shuttingDown {
+		return
+	}
+
+	for informerType, informer := range f.informers {
+		if !f.startedInformers[informerType] {
+			f.wg.Add(1)
+			// We need a new variable in each loop iteration,
+			// otherwise the goroutine would use the loop variable
+			// and that keeps changing.
+			informer := informer
+			go func() {
+				defer f.wg.Done()
+				informer.Run(stopCh)
+			}()
+			f.startedInformers[informerType] = true
+		}
+	}
+}
+
+func (f *sharedInformerFactory) Shutdown() {
+	f.lock.Lock()
+	f.shuttingDown = true
+	f.lock.Unlock()
+
+	// Will return immediately if there is nothing to wait for.
+	f.wg.Wait()
+}
+
+func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
+	informers := func() map[reflect.Type]cache.SharedIndexInformer {
+		f.lock.Lock()
+		defer f.lock.Unlock()
+
+		informers := map[reflect.Type]cache.SharedIndexInformer{}
+		for informerType, informer := range f.informers {
+			if f.startedInformers[informerType] {
+				informers[informerType] = informer
+			}
+		}
+		return informers
+	}()
+
+	res := map[reflect.Type]bool{}
+	for informType, informer := range informers {
+		res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
+	}
+	return res
+}
+
+// InternalInformerFor returns the SharedIndexInformer for obj using an internal
+// client.
+func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
+	f.lock.Lock()
+	defer f.lock.Unlock()
+
+	informerType := reflect.TypeOf(obj)
+	informer, exists := f.informers[informerType]
+	if exists {
+		return informer
+	}
+
+	resyncPeriod, exists := f.customResync[informerType]
+	if !exists {
+		resyncPeriod = f.defaultResync
+	}
+
+	informer = newFunc(f.client, resyncPeriod)
+	f.informers[informerType] = informer
+
+	return informer
+}
+
+// SharedInformerFactory provides shared informers for resources in all known
+// API group versions.
+//
+// It is typically used like this:
+//
+//	ctx, cancel := context.Background()
+//	defer cancel()
+//	factory := NewSharedInformerFactory(client, resyncPeriod)
+//	defer factory.WaitForStop()    // Returns immediately if nothing was started.
+//	genericInformer := factory.ForResource(resource)
+//	typedInformer := factory.SomeAPIGroup().V1().SomeType()
+//	factory.Start(ctx.Done())          // Start processing these informers.
+//	synced := factory.WaitForCacheSync(ctx.Done())
+//	for v, ok := range synced {
+//	    if !ok {
+//	        fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v)
+//	        return
+//	    }
+//	}
+//
+//	// Creating informers can also be created after Start, but then
+//	// Start must be called again:
+//	anotherGenericInformer := factory.ForResource(resource)
+//	factory.Start(ctx.Done())
+type SharedInformerFactory interface {
+	internalinterfaces.SharedInformerFactory
+
+	// Start initializes all requested informers. They are handled in goroutines
+	// which run until the stop channel gets closed.
+	Start(stopCh <-chan struct{})
+
+	// Shutdown marks a factory as shutting down. At that point no new
+	// informers can be started anymore and Start will return without
+	// doing anything.
+	//
+	// In addition, Shutdown blocks until all goroutines have terminated. For that
+	// to happen, the close channel(s) that they were started with must be closed,
+	// either before Shutdown gets called or while it is waiting.
+	//
+	// Shutdown may be called multiple times, even concurrently. All such calls will
+	// block until all goroutines have terminated.
+	Shutdown()
+
+	// WaitForCacheSync blocks until all started informers' caches were synced
+	// or the stop channel gets closed.
+	WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
+
+	// ForResource gives generic access to a shared informer of the matching type.
+	ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
+
+	// InternalInformerFor returns the SharedIndexInformer for obj using an internal
+	// client.
+	InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer
+
+	Dubbo() dubboapacheorg.Interface
+}
+
+func (f *sharedInformerFactory) Dubbo() dubboapacheorg.Interface {
+	return dubboapacheorg.New(f, f.namespace, f.tweakListOptions)
+}
diff --git a/pkg/mapping/generated/informers/externalversions/generic.go b/pkg/mapping/generated/informers/externalversions/generic.go
new file mode 100644
index 00000000..87dd38b8
--- /dev/null
+++ b/pkg/mapping/generated/informers/externalversions/generic.go
@@ -0,0 +1,62 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package externalversions
+
+import (
+	"fmt"
+	v1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
+// sharedInformers based on type
+type GenericInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() cache.GenericLister
+}
+
+type genericInformer struct {
+	informer cache.SharedIndexInformer
+	resource schema.GroupResource
+}
+
+// Informer returns the SharedIndexInformer.
+func (f *genericInformer) Informer() cache.SharedIndexInformer {
+	return f.informer
+}
+
+// Lister returns the GenericLister.
+func (f *genericInformer) Lister() cache.GenericLister {
+	return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
+}
+
+// ForResource gives generic access to a shared informer of the matching type
+// TODO extend this to unknown resources with a client pool
+func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
+	switch resource {
+	// Group=dubbo.apache.org, Version=v1alpha1
+	case v1alpha1.SchemeGroupVersion.WithResource("servicenamemappings"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Dubbo().V1alpha1().ServiceNameMappings().Informer()}, nil
+
+	}
+
+	return nil, fmt.Errorf("no informer found for %v", resource)
+}
diff --git a/pkg/mapping/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/mapping/generated/informers/externalversions/internalinterfaces/factory_interfaces.go
new file mode 100644
index 00000000..bcfaeff3
--- /dev/null
+++ b/pkg/mapping/generated/informers/externalversions/internalinterfaces/factory_interfaces.go
@@ -0,0 +1,40 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package internalinterfaces
+
+import (
+	versioned "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned"
+	time "time"
+
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
+type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
+
+// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
+type SharedInformerFactory interface {
+	Start(stopCh <-chan struct{})
+	InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
+}
+
+// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
+type TweakListOptionsFunc func(*v1.ListOptions)
diff --git a/pkg/mapping/generated/listers/dubbo.apache.org/v1alpha1/expansion_generated.go b/pkg/mapping/generated/listers/dubbo.apache.org/v1alpha1/expansion_generated.go
new file mode 100644
index 00000000..ef7453f3
--- /dev/null
+++ b/pkg/mapping/generated/listers/dubbo.apache.org/v1alpha1/expansion_generated.go
@@ -0,0 +1,27 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1alpha1
+
+// ServiceNameMappingListerExpansion allows custom methods to be added to
+// ServiceNameMappingLister.
+type ServiceNameMappingListerExpansion interface{}
+
+// ServiceNameMappingNamespaceListerExpansion allows custom methods to be added to
+// ServiceNameMappingNamespaceLister.
+type ServiceNameMappingNamespaceListerExpansion interface{}
diff --git a/pkg/mapping/generated/listers/dubbo.apache.org/v1alpha1/servicenamemapping.go b/pkg/mapping/generated/listers/dubbo.apache.org/v1alpha1/servicenamemapping.go
new file mode 100644
index 00000000..3e202f2a
--- /dev/null
+++ b/pkg/mapping/generated/listers/dubbo.apache.org/v1alpha1/servicenamemapping.go
@@ -0,0 +1,100 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	v1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+)
+
+// ServiceNameMappingLister helps list ServiceNameMappings.
+// All objects returned here must be treated as read-only.
+type ServiceNameMappingLister interface {
+	// List lists all ServiceNameMappings in the indexer.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v1alpha1.ServiceNameMapping, err error)
+	// ServiceNameMappings returns an object that can list and get ServiceNameMappings.
+	ServiceNameMappings(namespace string) ServiceNameMappingNamespaceLister
+	ServiceNameMappingListerExpansion
+}
+
+// serviceNameMappingLister implements the ServiceNameMappingLister interface.
+type serviceNameMappingLister struct {
+	indexer cache.Indexer
+}
+
+// NewServiceNameMappingLister returns a new ServiceNameMappingLister.
+func NewServiceNameMappingLister(indexer cache.Indexer) ServiceNameMappingLister {
+	return &serviceNameMappingLister{indexer: indexer}
+}
+
+// List lists all ServiceNameMappings in the indexer.
+func (s *serviceNameMappingLister) List(selector labels.Selector) (ret []*v1alpha1.ServiceNameMapping, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v1alpha1.ServiceNameMapping))
+	})
+	return ret, err
+}
+
+// ServiceNameMappings returns an object that can list and get ServiceNameMappings.
+func (s *serviceNameMappingLister) ServiceNameMappings(namespace string) ServiceNameMappingNamespaceLister {
+	return serviceNameMappingNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ServiceNameMappingNamespaceLister helps list and get ServiceNameMappings.
+// All objects returned here must be treated as read-only.
+type ServiceNameMappingNamespaceLister interface {
+	// List lists all ServiceNameMappings in the indexer for a given namespace.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v1alpha1.ServiceNameMapping, err error)
+	// Get retrieves the ServiceNameMapping from the indexer for a given namespace and name.
+	// Objects returned here must be treated as read-only.
+	Get(name string) (*v1alpha1.ServiceNameMapping, error)
+	ServiceNameMappingNamespaceListerExpansion
+}
+
+// serviceNameMappingNamespaceLister implements the ServiceNameMappingNamespaceLister
+// interface.
+type serviceNameMappingNamespaceLister struct {
+	indexer   cache.Indexer
+	namespace string
+}
+
+// List lists all ServiceNameMappings in the indexer for a given namespace.
+func (s serviceNameMappingNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ServiceNameMapping, err error) {
+	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+		ret = append(ret, m.(*v1alpha1.ServiceNameMapping))
+	})
+	return ret, err
+}
+
+// Get retrieves the ServiceNameMapping from the indexer for a given namespace and name.
+func (s serviceNameMappingNamespaceLister) Get(name string) (*v1alpha1.ServiceNameMapping, error) {
+	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v1alpha1.Resource("servicenamemapping"), name)
+	}
+	return obj.(*v1alpha1.ServiceNameMapping), nil
+}
diff --git a/pkg/mapping/kube/client.go b/pkg/mapping/kube/client.go
new file mode 100644
index 00000000..e2487685
--- /dev/null
+++ b/pkg/mapping/kube/client.go
@@ -0,0 +1,137 @@
+/*
+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.
+*/
+
+package kube
+
+import (
+	"flag"
+	"fmt"
+	"github.com/apache/dubbo-admin/pkg/logger"
+	corev1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+	"github.com/apache/dubbo-admin/pkg/mapping/config"
+	clientsetClient "github.com/apache/dubbo-admin/pkg/mapping/generated/clientset/versioned"
+	informers "github.com/apache/dubbo-admin/pkg/mapping/generated/informers/externalversions"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/rest"
+	"k8s.io/client-go/tools/clientcmd"
+	"k8s.io/client-go/util/homedir"
+	"os"
+	"path/filepath"
+	"time"
+)
+
+var kubeconfig string
+
+func init() {
+	flag.StringVar(&kubeconfig, "kubeconfig", "",
+		"Paths to a kubeconfig. Only required if out-of-cluster.")
+}
+
+type Client interface {
+	Init(options *config.Options) bool
+	Admin() clientsetClient.Interface
+	InitContainer()
+}
+
+type client struct {
+	options        *config.Options
+	kube           kubernetes.Interface
+	informerClient *clientsetClient.Clientset
+	kubeClient     *kubernetes.Clientset
+}
+
+func NewClient() Client {
+	return &client{}
+}
+
+func (c *client) Admin() clientsetClient.Interface {
+	return c.informerClient
+}
+
+func (c *client) Init(options *config.Options) bool {
+	c.options = options
+	config, err := rest.InClusterConfig()
+	if err != nil {
+		if len(kubeconfig) <= 0 {
+			kubeconfig = os.Getenv(clientcmd.RecommendedConfigPathEnvVar)
+			if len(kubeconfig) <= 0 {
+				if home := homedir.HomeDir(); home != "" {
+					kubeconfig = filepath.Join(home, ".kube", "config")
+				}
+			}
+		}
+		logger.Sugar().Infof("Read kubeconfig from %s", kubeconfig)
+		config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
+		if err != nil {
+			logger.Sugar().Warnf("Failed to load config from kube config file.")
+			return false
+		}
+	}
+	clientSet, err := kubernetes.NewForConfig(config)
+	if err != nil {
+		logger.Sugar().Warnf("Failed to create client to kubernetes. " + err.Error())
+		return false
+	}
+	informerClient, err := clientsetClient.NewForConfig(config)
+	if err != nil {
+		logger.Sugar().Warnf("Failed to create client to kubernetes. " + err.Error())
+		return false
+	}
+	service := &corev1.ServiceNameMapping{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "my-app",
+			Namespace: "default",
+			Annotations: map[string]string{
+				"dubbo.apache.org/application": "dubbo-admin",
+				"dubbo.apache.org/protocol":    "dubbo",
+			},
+		},
+		Spec: corev1.ServiceNameMappingSpec{
+			InterfaceName: "dubbo",
+			ApplicationNames: []string{
+				"dubbo-admin",
+			},
+		},
+	}
+	if err != nil {
+		fmt.Printf("Failed to convert service to unstructured: %v\n", err)
+		os.Exit(1)
+	}
+	logger.Sugar().Infof("Service created: %s\n", service.Name)
+	if err != nil {
+		logger.Sugar().Errorf("Failed to convert service to unstructured: %v\n", err)
+		os.Exit(1)
+	}
+	c.kubeClient = clientSet
+	c.informerClient = informerClient
+
+	return true
+
+}
+
+func (c *client) InitContainer() {
+	logger.Sugar().Info("Init controller...")
+	informerFactory := informers.NewSharedInformerFactory(c.informerClient, time.Second*10)
+	controller := NewController(informerFactory.Dubbo().V1alpha1().ServiceNameMappings())
+	stopCh := make(chan struct{})
+	informerFactory.Start(stopCh)
+	err := controller.PreRun(1, stopCh)
+	if err != nil {
+		return
+	}
+}
diff --git a/pkg/mapping/kube/controller.go b/pkg/mapping/kube/controller.go
new file mode 100644
index 00000000..2a845199
--- /dev/null
+++ b/pkg/mapping/kube/controller.go
@@ -0,0 +1,155 @@
+/*
+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.
+*/
+
+package kube
+
+import (
+	"fmt"
+	"github.com/apache/dubbo-admin/pkg/logger"
+	crdV1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/apis/dubbo.apache.org/v1alpha1"
+	informerV1alpha1 "github.com/apache/dubbo-admin/pkg/mapping/generated/informers/externalversions/dubbo.apache.org/v1alpha1"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/util/runtime"
+	"k8s.io/apimachinery/pkg/util/wait"
+	"k8s.io/client-go/tools/cache"
+	"k8s.io/client-go/util/workqueue"
+	"time"
+)
+
+type Controller struct {
+	informer       informerV1alpha1.ServiceNameMappingInformer
+	workqueue      workqueue.RateLimitingInterface
+	informerSynced cache.InformerSynced
+}
+
+func NewController(spInformer informerV1alpha1.ServiceNameMappingInformer) *Controller {
+	controller := &Controller{
+		informer:  spInformer,
+		workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "ServiceMappings"),
+	}
+	logger.Sugar().Info("Setting up service mappings event handlers")
+	_, err := spInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
+		AddFunc: controller.enqueueServiceMapping,
+		UpdateFunc: func(old, new interface{}) {
+			oldObj := old.(*crdV1alpha1.ServiceNameMapping)
+			newObj := new.(*crdV1alpha1.ServiceNameMapping)
+			if oldObj.ResourceVersion == newObj.ResourceVersion {
+				return
+			}
+			controller.enqueueServiceMapping(new)
+		},
+		DeleteFunc: controller.enqueueServiceMappingForDelete,
+	})
+	if err != nil {
+		return nil
+	}
+	return controller
+}
+
+func (c *Controller) Process() bool {
+	obj, shutdown := c.workqueue.Get()
+	if shutdown {
+		return false
+	}
+	err := func(obj interface{}) error {
+		defer c.workqueue.Done(obj)
+		var key string
+		var ok bool
+		if key, ok = obj.(string); !ok {
+			c.workqueue.Forget(obj)
+			runtime.HandleError(fmt.Errorf("expected string in workqueue but got %#v", obj))
+			return nil
+		}
+		if err := c.syncHandler(key); err != nil {
+			logger.Sugar().Error("error syncing '%s': %s", key, err.Error())
+			return nil
+		}
+		c.workqueue.Forget(obj)
+		logger.Sugar().Infof("Successfully synced %s", key)
+		return nil
+	}(obj)
+
+	if err != nil {
+		runtime.HandleError(err)
+		return true
+	}
+	return true
+}
+func (c *Controller) PreRun(thread int, stopCh <-chan struct{}) error {
+	defer runtime.HandleCrash()
+	defer c.workqueue.ShutDown()
+
+	logger.Sugar().Info("Starting Service Mapping control loop")
+	logger.Sugar().Info("Waiting for informer caches to sync")
+	logger.Sugar().Info("Starting sync")
+	for i := 0; i < thread; i++ {
+		go wait.Until(c.Run, time.Second, stopCh)
+	}
+	logger.Sugar().Info("Started sync")
+	<-stopCh
+	logger.Sugar().Info("Shutting down")
+	return nil
+}
+
+func (c *Controller) Run() {
+	for c.Process() {
+	}
+}
+
+func (c *Controller) syncHandler(key string) error {
+	namespace, name, err := cache.SplitMetaNamespaceKey(key)
+	if err != nil {
+		runtime.HandleError(fmt.Errorf("invalid resource key: %s", key))
+		return nil
+	}
+
+	sp, err := c.informer.Lister().ServiceNameMappings(namespace).Get(name)
+
+	if err != nil {
+		if errors.IsNotFound(err) {
+			logger.Sugar().Warnf("[ServiceMappingsCRD] %s/%s does not exist in local cache, will delete it from service mapping ...",
+				namespace, name)
+			logger.Sugar().Infof("[ServiceMappingsCRD] deleting service mapping: %s/%s ...", namespace, name)
+			return nil
+		}
+		runtime.HandleError(fmt.Errorf("failed to get service mapping by: %s/%s", namespace, name))
+		return err
+	}
+	logger.Sugar().Infof("[ServiceMappingsCRD] Trying to handle service mapping: %#v ...", sp)
+	return nil
+}
+
+func (c *Controller) enqueueServiceMapping(obj interface{}) {
+	var key string
+	var err error
+	if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
+		runtime.HandleError(err)
+		return
+	}
+	c.workqueue.AddRateLimited(key)
+}
+
+func (c *Controller) enqueueServiceMappingForDelete(obj interface{}) {
+	var key string
+	var err error
+	key, err = cache.DeletionHandlingMetaNamespaceKeyFunc(obj)
+	if err != nil {
+		runtime.HandleError(err)
+		return
+	}
+	c.workqueue.AddRateLimited(key)
+}
diff --git a/pkg/mapping/model/config.go b/pkg/mapping/model/config.go
new file mode 100644
index 00000000..6f0ec5d8
--- /dev/null
+++ b/pkg/mapping/model/config.go
@@ -0,0 +1,32 @@
+/*
+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.
+*/
+
+package model
+
+type Config struct {
+	Spec   Spec
+	Status Status
+}
+
+type ConfigKey struct {
+	Name      string
+	Namespace string
+}
+
+type Spec interface{}
+
+type Status interface{}
diff --git a/pkg/mapping/v1alpha1/servicenamemapping.pb.go b/pkg/mapping/v1alpha1/servicenamemapping.pb.go
new file mode 100644
index 00000000..d05f85b9
--- /dev/null
+++ b/pkg/mapping/v1alpha1/servicenamemapping.pb.go
@@ -0,0 +1,154 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.28.1
+// 	protoc        v3.21.5
+// source: servicenamemapping.proto
+
+package v1alpha1
+
+import (
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+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 ServiceNameMapping struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	InterfaceName    string   `protobuf:"bytes,1,opt,name=interfaceName,proto3" json:"interfaceName,omitempty"`
+	ApplicationNames []string `protobuf:"bytes,2,rep,name=applicationNames,proto3" json:"applicationNames,omitempty"`
+}
+
+func (x *ServiceNameMapping) Reset() {
+	*x = ServiceNameMapping{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_servicenamemapping_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ServiceNameMapping) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServiceNameMapping) ProtoMessage() {}
+
+func (x *ServiceNameMapping) ProtoReflect() protoreflect.Message {
+	mi := &file_servicenamemapping_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ServiceNameMapping.ProtoReflect.Descriptor instead.
+func (*ServiceNameMapping) Descriptor() ([]byte, []int) {
+	return file_servicenamemapping_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *ServiceNameMapping) GetInterfaceName() string {
+	if x != nil {
+		return x.InterfaceName
+	}
+	return ""
+}
+
+func (x *ServiceNameMapping) GetApplicationNames() []string {
+	if x != nil {
+		return x.ApplicationNames
+	}
+	return nil
+}
+
+var File_servicenamemapping_proto protoreflect.FileDescriptor
+
+var file_servicenamemapping_proto_rawDesc = []byte{
+	0x0a, 0x18, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x6d, 0x61, 0x70,
+	0x70, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x76, 0x31, 0x61, 0x6c,
+	0x70, 0x68, 0x61, 0x31, 0x22, 0x66, 0x0a, 0x12, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e,
+	0x61, 0x6d, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x6e,
+	0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65,
+	0x12, 0x2a, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e,
+	0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x70, 0x70, 0x6c,
+	0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x42, 0x04, 0x5a, 0x02,
+	0x2e, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_servicenamemapping_proto_rawDescOnce sync.Once
+	file_servicenamemapping_proto_rawDescData = file_servicenamemapping_proto_rawDesc
+)
+
+func file_servicenamemapping_proto_rawDescGZIP() []byte {
+	file_servicenamemapping_proto_rawDescOnce.Do(func() {
+		file_servicenamemapping_proto_rawDescData = protoimpl.X.CompressGZIP(file_servicenamemapping_proto_rawDescData)
+	})
+	return file_servicenamemapping_proto_rawDescData
+}
+
+var file_servicenamemapping_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_servicenamemapping_proto_goTypes = []interface{}{
+	(*ServiceNameMapping)(nil), // 0: v1alpha1.ServiceNameMapping
+}
+var file_servicenamemapping_proto_depIdxs = []int32{
+	0, // [0:0] is the sub-list for method output_type
+	0, // [0:0] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_servicenamemapping_proto_init() }
+func file_servicenamemapping_proto_init() {
+	if File_servicenamemapping_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_servicenamemapping_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ServiceNameMapping); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_servicenamemapping_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   1,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_servicenamemapping_proto_goTypes,
+		DependencyIndexes: file_servicenamemapping_proto_depIdxs,
+		MessageInfos:      file_servicenamemapping_proto_msgTypes,
+	}.Build()
+	File_servicenamemapping_proto = out.File
+	file_servicenamemapping_proto_rawDesc = nil
+	file_servicenamemapping_proto_goTypes = nil
+	file_servicenamemapping_proto_depIdxs = nil
+}
diff --git a/pkg/mapping/v1alpha1/servicenamemapping.proto b/pkg/mapping/v1alpha1/servicenamemapping.proto
new file mode 100644
index 00000000..320184be
--- /dev/null
+++ b/pkg/mapping/v1alpha1/servicenamemapping.proto
@@ -0,0 +1,15 @@
+syntax = "proto3";
+
+package v1alpha1;
+
+option go_package="./";
+
+// +kubetype-gen
+// +kubetype-gen:groupVersion=dubbo.apache.org/v1alpha1
+// +genclient
+// +k8s:deepcopy-gen=true
+
+message ServiceNameMapping{
+  string interfaceName = 1;
+  repeated string applicationNames = 2;
+}
\ No newline at end of file
diff --git a/pkg/mapping/v1alpha1/snp.pb.go b/pkg/mapping/v1alpha1/snp.pb.go
new file mode 100644
index 00000000..f79c1e1b
--- /dev/null
+++ b/pkg/mapping/v1alpha1/snp.pb.go
@@ -0,0 +1,315 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.28.1
+// 	protoc        v3.21.5
+// source: snp.proto
+
+package v1alpha1
+
+import (
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+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)
+)
+
+// When dubbo provider start up, it reports its applicationName and its interfaceName,
+// and Dubbo consumer will get the service name mapping info by xDS.
+type ServiceMappingRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// This is namespace of proxyless dubbo server
+	Namespace       string   `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
+	ApplicationName string   `protobuf:"bytes,2,opt,name=applicationName,proto3" json:"applicationName,omitempty"`
+	InterfaceNames  []string `protobuf:"bytes,3,rep,name=interfaceNames,proto3" json:"interfaceNames,omitempty"`
+}
+
+func (x *ServiceMappingRequest) Reset() {
+	*x = ServiceMappingRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_snp_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ServiceMappingRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServiceMappingRequest) ProtoMessage() {}
+
+func (x *ServiceMappingRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_snp_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ServiceMappingRequest.ProtoReflect.Descriptor instead.
+func (*ServiceMappingRequest) Descriptor() ([]byte, []int) {
+	return file_snp_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *ServiceMappingRequest) GetNamespace() string {
+	if x != nil {
+		return x.Namespace
+	}
+	return ""
+}
+
+func (x *ServiceMappingRequest) GetApplicationName() string {
+	if x != nil {
+		return x.ApplicationName
+	}
+	return ""
+}
+
+func (x *ServiceMappingRequest) GetInterfaceNames() []string {
+	if x != nil {
+		return x.InterfaceNames
+	}
+	return nil
+}
+
+type ServiceMappingResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *ServiceMappingResponse) Reset() {
+	*x = ServiceMappingResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_snp_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ServiceMappingResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServiceMappingResponse) ProtoMessage() {}
+
+func (x *ServiceMappingResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_snp_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ServiceMappingResponse.ProtoReflect.Descriptor instead.
+func (*ServiceMappingResponse) Descriptor() ([]byte, []int) {
+	return file_snp_proto_rawDescGZIP(), []int{1}
+}
+
+type ServiceMappingXdsResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// This is namespace of proxyless dubbo server
+	Namespace        string   `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
+	InterfaceName    string   `protobuf:"bytes,2,opt,name=interfaceName,proto3" json:"interfaceName,omitempty"`
+	ApplicationNames []string `protobuf:"bytes,3,rep,name=applicationNames,proto3" json:"applicationNames,omitempty"`
+}
+
+func (x *ServiceMappingXdsResponse) Reset() {
+	*x = ServiceMappingXdsResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_snp_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ServiceMappingXdsResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServiceMappingXdsResponse) ProtoMessage() {}
+
+func (x *ServiceMappingXdsResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_snp_proto_msgTypes[2]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ServiceMappingXdsResponse.ProtoReflect.Descriptor instead.
+func (*ServiceMappingXdsResponse) Descriptor() ([]byte, []int) {
+	return file_snp_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ServiceMappingXdsResponse) GetNamespace() string {
+	if x != nil {
+		return x.Namespace
+	}
+	return ""
+}
+
+func (x *ServiceMappingXdsResponse) GetInterfaceName() string {
+	if x != nil {
+		return x.InterfaceName
+	}
+	return ""
+}
+
+func (x *ServiceMappingXdsResponse) GetApplicationNames() []string {
+	if x != nil {
+		return x.ApplicationNames
+	}
+	return nil
+}
+
+var File_snp_proto protoreflect.FileDescriptor
+
+var file_snp_proto_rawDesc = []byte{
+	0x0a, 0x09, 0x73, 0x6e, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x76, 0x31, 0x61,
+	0x6c, 0x70, 0x68, 0x61, 0x31, 0x22, 0x87, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
+	0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x28, 0x0a,
+	0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72,
+	0x66, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
+	0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22,
+	0x18, 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e,
+	0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x19, 0x53, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x58, 0x64, 0x73, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73,
+	0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65,
+	0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61,
+	0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x6e,
+	0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x61,
+	0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18,
+	0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x32, 0x7b, 0x0a, 0x19, 0x53, 0x65, 0x72, 0x76, 0x69,
+	0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72,
+	0x76, 0x69, 0x63, 0x65, 0x12, 0x5e, 0x0a, 0x19, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x70, 0x70, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e,
+	0x67, 0x12, 0x1f, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x72,
+	0x76, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x20, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x42, 0x04, 0x5a, 0x02, 0x2e, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x33,
+}
+
+var (
+	file_snp_proto_rawDescOnce sync.Once
+	file_snp_proto_rawDescData = file_snp_proto_rawDesc
+)
+
+func file_snp_proto_rawDescGZIP() []byte {
+	file_snp_proto_rawDescOnce.Do(func() {
+		file_snp_proto_rawDescData = protoimpl.X.CompressGZIP(file_snp_proto_rawDescData)
+	})
+	return file_snp_proto_rawDescData
+}
+
+var file_snp_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_snp_proto_goTypes = []interface{}{
+	(*ServiceMappingRequest)(nil),     // 0: v1alpha1.ServiceMappingRequest
+	(*ServiceMappingResponse)(nil),    // 1: v1alpha1.ServiceMappingResponse
+	(*ServiceMappingXdsResponse)(nil), // 2: v1alpha1.ServiceMappingXdsResponse
+}
+var file_snp_proto_depIdxs = []int32{
+	0, // 0: v1alpha1.ServiceNameMappingService.registerServiceAppMapping:input_type -> v1alpha1.ServiceMappingRequest
+	1, // 1: v1alpha1.ServiceNameMappingService.registerServiceAppMapping:output_type -> v1alpha1.ServiceMappingResponse
+	1, // [1:2] is the sub-list for method output_type
+	0, // [0:1] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_snp_proto_init() }
+func file_snp_proto_init() {
+	if File_snp_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_snp_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ServiceMappingRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_snp_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ServiceMappingResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_snp_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ServiceMappingXdsResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_snp_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   3,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_snp_proto_goTypes,
+		DependencyIndexes: file_snp_proto_depIdxs,
+		MessageInfos:      file_snp_proto_msgTypes,
+	}.Build()
+	File_snp_proto = out.File
+	file_snp_proto_rawDesc = nil
+	file_snp_proto_goTypes = nil
+	file_snp_proto_depIdxs = nil
+}
diff --git a/pkg/mapping/v1alpha1/snp.proto b/pkg/mapping/v1alpha1/snp.proto
new file mode 100644
index 00000000..1c207cab
--- /dev/null
+++ b/pkg/mapping/v1alpha1/snp.proto
@@ -0,0 +1,35 @@
+syntax = "proto3";
+
+package v1alpha1;
+
+option go_package = "./";
+
+// Provides an service for reporting the mapping relationship between interface => cluster
+// the cluster name will be versioned FQDN. such as "demo.default.svc.cluster.local"
+service ServiceNameMappingService{
+  rpc registerServiceAppMapping(ServiceMappingRequest) returns (ServiceMappingResponse);
+}
+
+// When dubbo provider start up, it reports its applicationName and its interfaceName,
+// and Dubbo consumer will get the service name mapping info by xDS.
+message ServiceMappingRequest{
+  // This is namespace of proxyless dubbo server
+  string namespace = 1;
+
+  string applicationName = 2;
+
+  repeated string interfaceNames = 3;
+}
+
+message ServiceMappingResponse{
+}
+
+
+message ServiceMappingXdsResponse{
+  // This is namespace of proxyless dubbo server
+  string namespace = 1;
+
+  string interfaceName = 2;
+
+  repeated string applicationNames = 3;
+}
\ No newline at end of file
diff --git a/pkg/mapping/v1alpha1/snp_grpc.pb.go b/pkg/mapping/v1alpha1/snp_grpc.pb.go
new file mode 100644
index 00000000..cb0d24ef
--- /dev/null
+++ b/pkg/mapping/v1alpha1/snp_grpc.pb.go
@@ -0,0 +1,110 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.3.0
+// - protoc             v3.21.5
+// source: snp.proto
+
+package v1alpha1
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+const (
+	ServiceNameMappingService_RegisterServiceAppMapping_FullMethodName = "/v1alpha1.ServiceNameMappingService/registerServiceAppMapping"
+)
+
+// ServiceNameMappingServiceClient is the client API for ServiceNameMappingService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type ServiceNameMappingServiceClient interface {
+	RegisterServiceAppMapping(ctx context.Context, in *ServiceMappingRequest, opts ...grpc.CallOption) (*ServiceMappingResponse, error)
+}
+
+type serviceNameMappingServiceClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewServiceNameMappingServiceClient(cc grpc.ClientConnInterface) ServiceNameMappingServiceClient {
+	return &serviceNameMappingServiceClient{cc}
+}
+
+func (c *serviceNameMappingServiceClient) RegisterServiceAppMapping(ctx context.Context, in *ServiceMappingRequest, opts ...grpc.CallOption) (*ServiceMappingResponse, error) {
+	out := new(ServiceMappingResponse)
+	err := c.cc.Invoke(ctx, ServiceNameMappingService_RegisterServiceAppMapping_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// ServiceNameMappingServiceServer is the server API for ServiceNameMappingService service.
+// All implementations must embed UnimplementedServiceNameMappingServiceServer
+// for forward compatibility
+type ServiceNameMappingServiceServer interface {
+	RegisterServiceAppMapping(context.Context, *ServiceMappingRequest) (*ServiceMappingResponse, error)
+	mustEmbedUnimplementedServiceNameMappingServiceServer()
+}
+
+// UnimplementedServiceNameMappingServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedServiceNameMappingServiceServer struct {
+}
+
+func (UnimplementedServiceNameMappingServiceServer) RegisterServiceAppMapping(context.Context, *ServiceMappingRequest) (*ServiceMappingResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method RegisterServiceAppMapping not implemented")
+}
+func (UnimplementedServiceNameMappingServiceServer) mustEmbedUnimplementedServiceNameMappingServiceServer() {
+}
+
+// UnsafeServiceNameMappingServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to ServiceNameMappingServiceServer will
+// result in compilation errors.
+type UnsafeServiceNameMappingServiceServer interface {
+	mustEmbedUnimplementedServiceNameMappingServiceServer()
+}
+
+func RegisterServiceNameMappingServiceServer(s grpc.ServiceRegistrar, srv ServiceNameMappingServiceServer) {
+	s.RegisterService(&ServiceNameMappingService_ServiceDesc, srv)
+}
+
+func _ServiceNameMappingService_RegisterServiceAppMapping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ServiceMappingRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ServiceNameMappingServiceServer).RegisterServiceAppMapping(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: ServiceNameMappingService_RegisterServiceAppMapping_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ServiceNameMappingServiceServer).RegisterServiceAppMapping(ctx, req.(*ServiceMappingRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+// ServiceNameMappingService_ServiceDesc is the grpc.ServiceDesc for ServiceNameMappingService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var ServiceNameMappingService_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "v1alpha1.ServiceNameMappingService",
+	HandlerType: (*ServiceNameMappingServiceServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "registerServiceAppMapping",
+			Handler:    _ServiceNameMappingService_RegisterServiceAppMapping_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "snp.proto",
+}