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

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

commit 33cba24936271cd07fa54a639ece9bfa18d4a178
Author: mfordjody <[email protected]>
AuthorDate: Mon Jul 3 11:24:25 2023 +0800

    Service name mapping (#1146)
    
    Co-authored-by: Ken Liu <[email protected]>
---
 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",
+}

Reply via email to