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
}