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

tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new 1734dab  [Enhancement] implement ms datasource register service in 
etcd mode (#697)
1734dab is described below

commit 1734dabcc53435973f1abd46e01d964450dfbd6c
Author: popozy <[email protected]>
AuthorDate: Fri Sep 25 16:48:07 2020 +0800

    [Enhancement] implement ms datasource register service in etcd mode (#697)
---
 server/service/microservice_test.go       |  19 ----
 server/service/ms/datasource.go           |   3 +-
 server/service/ms/etcd/etcd.go            |  88 +++++++++++++--
 server/service/ms/etcd/etcd_suite_test.go |  55 ++++++++++
 server/service/ms/etcd/etcd_test.go       | 177 ++++++++++++++++++++++++++++++
 server/service/ms/manager_test.go         |  39 ++-----
 server/service/ms/options.go              |   2 +
 7 files changed, 322 insertions(+), 61 deletions(-)

diff --git a/server/service/microservice_test.go 
b/server/service/microservice_test.go
index 2d8e779..ce8b0ba 100644
--- a/server/service/microservice_test.go
+++ b/server/service/microservice_test.go
@@ -22,9 +22,6 @@ import (
        "github.com/apache/servicecomb-service-center/server/core/proto"
        "github.com/apache/servicecomb-service-center/server/plugin/quota"
        scerr "github.com/apache/servicecomb-service-center/server/scerror"
-       "github.com/apache/servicecomb-service-center/server/service/ms"
-       "github.com/apache/servicecomb-service-center/server/service/ms/etcd"
-       "github.com/go-chassis/go-archaius"
        . "github.com/onsi/ginkgo"
        . "github.com/onsi/gomega"
        "strconv"
@@ -52,22 +49,6 @@ var _ = Describe("'Micro-service' service", func() {
                                Expect(err).To(BeNil())
                                
Expect(resp.Response.GetCode()).To(Equal(scerr.ErrInvalidParams))
                        })
-
-                       It("ms datasource etcd mode: should not be passed", 
func() {
-                               ms.Install("etcd",
-                                       func(opts ms.Options) (ms.DataSource, 
error) {
-                                               return etcd.NewDataSource(), nil
-                                       })
-
-                               // sc main function initialize step
-                               err := ms.Init(ms.Options{
-                                       Endpoint:       "",
-                                       PluginImplName: 
ms.ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
-                               })
-                               resp, err := 
ms.MicroService().RegisterService(getContext(), 
&pb.CreateServiceRequest{Service: nil})
-                               Expect(err).To(BeNil())
-                               
Expect(resp.Response.GetCode()).To(Equal(scerr.ErrInvalidParams))
-                       })
                })
 
                Context("all max", func() {
diff --git a/server/service/ms/datasource.go b/server/service/ms/datasource.go
index f704a84..8380814 100644
--- a/server/service/ms/datasource.go
+++ b/server/service/ms/datasource.go
@@ -18,10 +18,11 @@ package ms
 import (
        "context"
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
+       "github.com/apache/servicecomb-service-center/server/plugin/registry"
 )
 
 type DataSource interface {
-       RegisterService(ctx context.Context, service *pb.CreateServiceRequest) 
(*pb.CreateServiceResponse, error)
+       RegisterService(ctx context.Context, service *pb.CreateServiceRequest) 
(*registry.PluginResponse, error)
        GetService(ctx context.Context, service *pb.GetServiceRequest)
        UpdateService(ctx context.Context, service 
*pb.UpdateServicePropsRequest)
        UnregisterService(ctx context.Context, service *pb.DeleteServiceRequest)
diff --git a/server/service/ms/etcd/etcd.go b/server/service/ms/etcd/etcd.go
index 10a6ba1..d91a017 100644
--- a/server/service/ms/etcd/etcd.go
+++ b/server/service/ms/etcd/etcd.go
@@ -17,10 +17,18 @@ package etcd
 
 import (
        "context"
+       "encoding/json"
        "github.com/apache/servicecomb-service-center/pkg/log"
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
-       "github.com/apache/servicecomb-service-center/server/core/proto"
-       scerr "github.com/apache/servicecomb-service-center/server/scerror"
+       "github.com/apache/servicecomb-service-center/pkg/util"
+       apt "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/backend"
+       "github.com/apache/servicecomb-service-center/server/plugin"
+       "github.com/apache/servicecomb-service-center/server/plugin/registry"
+       "github.com/apache/servicecomb-service-center/server/plugin/uuid"
+       serviceUtil 
"github.com/apache/servicecomb-service-center/server/service/util"
+       "strconv"
+       "time"
 )
 
 // TODO: define error with names here
@@ -37,7 +45,6 @@ func NewDataSource() *DataSource {
        log.Warnf("microservice mgt data source enable etcd mode")
 
        inst := &DataSource{}
-       // TODO: deal with exception
        if err := inst.initialize(); err != nil {
                return inst
        }
@@ -49,14 +56,75 @@ func (ds *DataSource) initialize() error {
        return nil
 }
 
-func (ds *DataSource) RegisterService(ctx context.Context, service 
*pb.CreateServiceRequest) (*pb.CreateServiceResponse, error) {
-       if service == nil || service.Service == nil {
-               log.Errorf(nil, "create micro-service failed: request body is 
empty")
-               return &pb.CreateServiceResponse{
-                       Response: proto.CreateResponse(scerr.ErrInvalidParams, 
"Request body is empty"),
-               }, nil
+// RegisterService() implement:
+// 1. capsule request to etcd kv format
+// 2. invoke registry interface to store service information to etcd cluster
+// Attention: parameters validation && response check must be checked outside 
the method
+func (ds *DataSource) RegisterService(ctx context.Context, request 
*pb.CreateServiceRequest) (
+       *registry.PluginResponse, error) {
+       remoteIP := util.GetIPFromContext(ctx)
+       serviceBody := request.Service
+       serviceFlag := util.StringJoin([]string{
+               serviceBody.Environment, serviceBody.AppId, 
serviceBody.ServiceName, serviceBody.Version}, "/")
+
+       serviceUtil.SetServiceDefaultValue(serviceBody)
+
+       domainProject := util.ParseDomainProject(ctx)
+
+       serviceKey := &pb.MicroServiceKey{
+               Tenant:      domainProject,
+               Environment: serviceBody.Environment,
+               AppId:       serviceBody.AppId,
+               ServiceName: serviceBody.ServiceName,
+               Alias:       serviceBody.Alias,
+               Version:     serviceBody.Version,
        }
-       return nil, nil
+
+       index := apt.GenerateServiceIndexKey(serviceKey)
+
+       // 产生全局service id
+       requestServiceID := serviceBody.ServiceId
+       if len(requestServiceID) == 0 {
+               ctx = util.SetContext(ctx, uuid.ContextKey, index)
+               serviceBody.ServiceId = 
plugin.Plugins().UUID().GetServiceID(ctx)
+       }
+       serviceBody.Timestamp = strconv.FormatInt(time.Now().Unix(), 10)
+       serviceBody.ModTimestamp = serviceBody.Timestamp
+
+       data, err := json.Marshal(serviceBody)
+       if err != nil {
+               log.Errorf(err, "create micro-serviceBody[%s] failed, json 
marshal serviceBody failed, operator: %s",
+                       serviceFlag, remoteIP)
+               return nil, err
+       }
+
+       key := apt.GenerateServiceKey(domainProject, serviceBody.ServiceId)
+       keyBytes := util.StringToBytesWithNoCopy(key)
+       indexBytes := util.StringToBytesWithNoCopy(index)
+       aliasBytes := 
util.StringToBytesWithNoCopy(apt.GenerateServiceAliasKey(serviceKey))
+
+       opts := []registry.PluginOp{
+               registry.OpPut(registry.WithKey(keyBytes), 
registry.WithValue(data)),
+               registry.OpPut(registry.WithKey(indexBytes), 
registry.WithStrValue(serviceBody.ServiceId)),
+       }
+       uniqueCmpOpts := []registry.CompareOp{
+               registry.OpCmp(registry.CmpVer(indexBytes), registry.CmpEqual, 
0),
+               registry.OpCmp(registry.CmpVer(keyBytes), registry.CmpEqual, 0),
+       }
+       failOpts := []registry.PluginOp{
+               registry.OpGet(registry.WithKey(indexBytes)),
+       }
+
+       if len(serviceKey.Alias) > 0 {
+               opts = append(opts, 
registry.OpPut(registry.WithKey(aliasBytes), 
registry.WithStrValue(serviceBody.ServiceId)))
+               uniqueCmpOpts = append(uniqueCmpOpts,
+                       registry.OpCmp(registry.CmpVer(aliasBytes), 
registry.CmpEqual, 0))
+               failOpts = append(failOpts, 
registry.OpGet(registry.WithKey(aliasBytes)))
+       }
+
+       resp, err := backend.Registry().TxnWithCmp(ctx, opts, uniqueCmpOpts, 
failOpts)
+
+       return resp, err
 }
 
 func (ds *DataSource) GetService(ctx context.Context, service 
*pb.GetServiceRequest) {
diff --git a/server/service/ms/etcd/etcd_suite_test.go 
b/server/service/ms/etcd/etcd_suite_test.go
new file mode 100644
index 0000000..e956a6d
--- /dev/null
+++ b/server/service/ms/etcd/etcd_suite_test.go
@@ -0,0 +1,55 @@
+/*
+ * 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 etcd_test
+
+// initialize
+import (
+       _ "github.com/apache/servicecomb-service-center/server/bootstrap"
+)
+import (
+       "context"
+       "github.com/apache/servicecomb-service-center/pkg/util"
+       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/astaxie/beego"
+       . "github.com/onsi/ginkgo"
+       "github.com/onsi/ginkgo/reporters"
+       . "github.com/onsi/gomega"
+       "testing"
+)
+
+func init() {
+       beego.AppConfig.Set("registry_plugin", "etcd")
+       testing.Init()
+       core.Initialize()
+}
+
+var _ = BeforeSuite(func() {
+       //init plugin
+       core.ServerInfo.Config.EnableCache = false
+})
+
+func getContext() context.Context {
+       return util.SetContext(
+               util.SetDomainProject(context.Background(), "default", 
"default"),
+               util.CtxNocache, "1")
+}
+
+func TestGrpc(t *testing.T) {
+       RegisterFailHandler(Fail)
+       junitReporter := reporters.NewJUnitReporter("model.junit.xml")
+       RunSpecsWithDefaultAndCustomReporters(t, "model Suite", 
[]Reporter{junitReporter})
+}
diff --git a/server/service/ms/etcd/etcd_test.go 
b/server/service/ms/etcd/etcd_test.go
new file mode 100644
index 0000000..5e78df3
--- /dev/null
+++ b/server/service/ms/etcd/etcd_test.go
@@ -0,0 +1,177 @@
+// 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 etcd_test
+
+import (
+       pb "github.com/apache/servicecomb-service-center/pkg/registry"
+       "github.com/apache/servicecomb-service-center/server/plugin/quota"
+       "github.com/apache/servicecomb-service-center/server/service/ms"
+       "github.com/apache/servicecomb-service-center/server/service/ms/etcd"
+       "github.com/go-chassis/go-archaius"
+       "github.com/stretchr/testify/assert"
+       "strconv"
+       "strings"
+       "testing"
+       "time"
+)
+
+var (
+       TooLongAppId       = strings.Repeat("x", 162)
+       TooLongSchemaId    = strings.Repeat("x", 162)
+       TooLongServiceName = strings.Repeat("x", 130)
+       TooLongAlias       = strings.Repeat("x", 130)
+       TooLongFramework   = strings.Repeat("x", 66)
+)
+
+func TestInit(t *testing.T) {
+       _ = archaius.Init(archaius.WithMemorySource())
+       _ = archaius.Set("servicecomb.ms.name", "etcd")
+
+       t.Run("Register service after init & install, should pass", func(t 
*testing.T) {
+               ms.Install("etcd", func(opts ms.Options) (ms.DataSource, error) 
{
+                       return etcd.NewDataSource(), nil
+               })
+
+               err := ms.Init(ms.Options{
+                       Endpoint:       "",
+                       PluginImplName: 
ms.ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
+               })
+               assert.NoError(t, err)
+
+               size := quota.DefaultSchemaQuota + 1
+               paths := make([]*pb.ServicePath, 0, size)
+               properties := make(map[string]string, size)
+               for i := 0; i < size; i++ {
+                       s := strconv.Itoa(i) + strings.Repeat("x", 253)
+                       paths = append(paths, &pb.ServicePath{Path: s, 
Property: map[string]string{s: s}})
+                       properties[s] = s
+               }
+               request := &pb.CreateServiceRequest{
+                       Service: &pb.MicroService{
+                               AppId:       TooLongAppId[:len(TooLongAppId)-1],
+                               ServiceName: 
TooLongServiceName[:len(TooLongServiceName)-1],
+                               Version:     "32767.32767.32767.32767",
+                               Alias:       TooLongAlias[:len(TooLongAlias)-1],
+                               Level:       "BACK",
+                               Status:      "UP",
+                               Schemas:     
[]string{TooLongSchemaId[:len(TooLongSchemaId)-1]},
+                               Paths:       paths,
+                               Properties:  properties,
+                               Framework: &pb.FrameWorkProperty{
+                                       Name:    
TooLongFramework[:len(TooLongFramework)-1],
+                                       Version: 
TooLongFramework[:len(TooLongFramework)-1],
+                               },
+                               RegisterBy: "SDK",
+                               Timestamp:  
strconv.FormatInt(time.Now().Unix(), 10),
+                       },
+               }
+               request.Service.ModTimestamp = request.Service.Timestamp
+               resp, err := ms.MicroService().RegisterService(getContext(), 
request)
+
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.True(t, resp.Succeeded)
+       })
+
+       t.Run("register service with framework name nil", func(t *testing.T) {
+               ms.Install("etcd", func(opts ms.Options) (ms.DataSource, error) 
{
+                       return etcd.NewDataSource(), nil
+               })
+
+               err := ms.Init(ms.Options{
+                       Endpoint:       "",
+                       PluginImplName: 
ms.ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
+               })
+               assert.NoError(t, err)
+
+               request := &pb.CreateServiceRequest{
+                       Service: &pb.MicroService{
+                               ServiceName: "framework-test-ms",
+                               AppId:       "default",
+                               Version:     "1.0.1",
+                               Level:       "BACK",
+                               Framework: &pb.FrameWorkProperty{
+                                       Version: "1.0.0",
+                               },
+                               Properties: make(map[string]string),
+                               Status:     "UP",
+                       },
+               }
+
+               resp, err := ms.MicroService().RegisterService(getContext(), 
request)
+
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.True(t, resp.Succeeded)
+       })
+
+       t.Run("register service with framework version nil", func(t *testing.T) 
{
+               ms.Install("etcd", func(opts ms.Options) (ms.DataSource, error) 
{
+                       return etcd.NewDataSource(), nil
+               })
+               err := ms.Init(ms.Options{
+                       Endpoint:       "",
+                       PluginImplName: 
ms.ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
+               })
+               assert.NoError(t, err)
+               request := &pb.CreateServiceRequest{
+                       Service: &pb.MicroService{
+                               ServiceName: "framework-test-ms",
+                               AppId:       "default",
+                               Version:     "1.0.2",
+                               Level:       "BACK",
+                               Framework: &pb.FrameWorkProperty{
+                                       Name: "framework",
+                               },
+                               Properties: make(map[string]string),
+                               Status:     "UP",
+                       },
+               }
+
+               resp, err := ms.MicroService().RegisterService(getContext(), 
request)
+
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.True(t, resp.Succeeded)
+       })
+
+       t.Run("register service with status is nil", func(t *testing.T) {
+               ms.Install("etcd", func(opts ms.Options) (ms.DataSource, error) 
{
+                       return etcd.NewDataSource(), nil
+               })
+               err := ms.Init(ms.Options{
+                       Endpoint:       "",
+                       PluginImplName: 
ms.ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
+               })
+               assert.NoError(t, err)
+
+               request := &pb.CreateServiceRequest{
+                       Service: &pb.MicroService{
+                               ServiceName: "status-test-ms",
+                               AppId:       "default",
+                               Version:     "1.0.3",
+                               Level:       "BACK",
+                               Properties:  make(map[string]string),
+                       },
+               }
+
+               resp, err := ms.MicroService().RegisterService(getContext(), 
request)
+
+               assert.NotNil(t, resp)
+               assert.NoError(t, err)
+               assert.True(t, resp.Succeeded)
+       })
+}
diff --git a/server/service/ms/manager_test.go 
b/server/service/ms/manager_test.go
index b8f594b..48a0a80 100644
--- a/server/service/ms/manager_test.go
+++ b/server/service/ms/manager_test.go
@@ -13,13 +13,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package ms
+package ms_test
 
 import (
-       "context"
-       pb "github.com/apache/servicecomb-service-center/pkg/registry"
-       "github.com/apache/servicecomb-service-center/pkg/util"
-       scerr "github.com/apache/servicecomb-service-center/server/scerror"
+       "github.com/apache/servicecomb-service-center/server/service/ms"
        "github.com/apache/servicecomb-service-center/server/service/ms/etcd"
        "github.com/go-chassis/go-archaius"
        "github.com/stretchr/testify/assert"
@@ -29,41 +26,21 @@ import (
 func TestInit(t *testing.T) {
        _ = archaius.Init(archaius.WithMemorySource())
        _ = archaius.Set("servicecomb.ms.name", "etcd")
-       t.Run("circuit microservice data source plugin", func(t *testing.T) {
-               err := Init(Options{
+       t.Run("init microservice data source plugin, should pass", func(t 
*testing.T) {
+               err := ms.Init(ms.Options{
                        Endpoint:       "",
                        PluginImplName: "",
                })
                assert.NoError(t, err)
        })
-       t.Run("microservice data source plugin install and init", func(t 
*testing.T) {
-               Install("etcd", func(opts Options) (DataSource, error) {
+       t.Run("install and init microservice data source plugin, should pass", 
func(t *testing.T) {
+               ms.Install("etcd", func(opts ms.Options) (ms.DataSource, error) 
{
                        return etcd.NewDataSource(), nil
                })
-               err := Init(Options{
+               err := ms.Init(ms.Options{
                        Endpoint:       "",
-                       PluginImplName: 
ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
+                       PluginImplName: 
ms.ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
                })
                assert.NoError(t, err)
        })
-       t.Run("Register service,should success", func(t *testing.T) {
-               Install("etcd", func(opts Options) (DataSource, error) {
-                       return etcd.NewDataSource(), nil
-               })
-
-               err := Init(Options{
-                       Endpoint:       "",
-                       PluginImplName: 
ImplName(archaius.GetString("servicecomb.ms.name", "etcd")),
-               })
-               assert.NoError(t, err)
-               resp, err := MicroService().RegisterService(getContext(), 
&pb.CreateServiceRequest{Service: nil})
-               assert.NotNil(t, resp)
-               assert.Equal(t, resp.Response.GetCode(), scerr.ErrInvalidParams)
-       })
-}
-
-func getContext() context.Context {
-       return util.SetContext(
-               util.SetDomainProject(context.Background(), "default", 
"default"),
-               util.CtxNocache, "1")
 }
diff --git a/server/service/ms/options.go b/server/service/ms/options.go
index 485bcf5..c608be1 100644
--- a/server/service/ms/options.go
+++ b/server/service/ms/options.go
@@ -19,4 +19,6 @@ package ms
 type Options struct {
        Endpoint       string
        PluginImplName ImplName
+
+       // TODO: pay attention to more net config like TLSConfig when coding
 }

Reply via email to