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 504c529 [SCB-2094] add schema/rule/service ut (#779)
504c529 is described below
commit 504c5297a7098fad07158ad6386795508aba0440
Author: panqian <[email protected]>
AuthorDate: Tue Dec 15 10:54:39 2020 +0800
[SCB-2094] add schema/rule/service ut (#779)
---
.github/workflows/golangci-lint.yml | 2 +-
datasource/etcd/util.go | 59 +-
datasource/mongo/client/errortypes.go | 14 +-
datasource/mongo/client/mongo.go | 25 +-
datasource/mongo/mongo.go | 32 +-
datasource/mongo/ms.go | 698 +++++++----
datasource/mongo/ms_test.go | 2228 ++++++++++++++++++++++++++++-----
datasource/mongo/util.go | 71 +-
datasource/ms_util.go | 71 +-
9 files changed, 2589 insertions(+), 611 deletions(-)
diff --git a/.github/workflows/golangci-lint.yml
b/.github/workflows/golangci-lint.yml
index f7041e5..a8963a9 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -10,4 +10,4 @@ jobs:
uses: golangci/golangci-lint-action@v2
with:
version: v1.29
- args: --timeout=5m
--skip-dirs='test,pkg/registry,.*/controller/(v3|v4)$,.*/bootstrap$,server/broker/brokerpb,examples,frontend,scctl,integration'
--out-format=colored-line-number --enable golint,gocyclo,goimports
--skip-files=.*_test.go$
\ No newline at end of file
+ args: --timeout=5m
--skip-dirs='test,.*/controller/(v3|v4)$,.*/bootstrap$,server/broker,examples,frontend,scctl,integration'
--out-format=colored-line-number --enable golint,gocyclo,goimports
--skip-files=.*_test.go$
\ No newline at end of file
diff --git a/datasource/etcd/util.go b/datasource/etcd/util.go
index 007869a..4b21e9d 100644
--- a/datasource/etcd/util.go
+++ b/datasource/etcd/util.go
@@ -23,6 +23,8 @@ import (
"strings"
"time"
+ "github.com/apache/servicecomb-service-center/datasource"
+
"github.com/apache/servicecomb-service-center/datasource/etcd/client"
"github.com/apache/servicecomb-service-center/datasource/etcd/kv"
"github.com/apache/servicecomb-service-center/datasource/etcd/path"
@@ -44,11 +46,6 @@ type ServiceDetailOpt struct {
options []string
}
-type GetInstanceCountByDomainResponse struct {
- err error
- countByDomain int64
-}
-
// schema
func getSchemaSummary(ctx context.Context, domainProject string, serviceID
string, schemaID string) (string, error) {
key := path.GenerateServiceSchemaSummaryKey(domainProject, serviceID,
schemaID)
@@ -386,30 +383,17 @@ func statistics(ctx context.Context, withShared bool)
(*pb.Statistics, error) {
return nil, err
}
- app := make(map[string]struct{}, respSvc.Count)
- svcWithNonVersion := make(map[string]struct{}, respSvc.Count)
- svcIDToNonVerKey := make(map[string]string, respSvc.Count)
+ var svcIDs []string
+ var svcKeys []*pb.MicroServiceKey
for _, keyValue := range respSvc.Kvs {
key := path.GetInfoFromSvcIndexKV(keyValue.Key)
- if !withShared && core.IsGlobal(key) {
- continue
- }
- if _, ok := app[key.AppId]; !ok {
- app[key.AppId] = struct{}{}
- }
-
- key.Version = ""
- svcWithNonVersionKey := path.GenerateServiceIndexKey(key)
- if _, ok := svcWithNonVersion[svcWithNonVersionKey]; !ok {
- svcWithNonVersion[svcWithNonVersionKey] = struct{}{}
- }
- svcIDToNonVerKey[keyValue.Value.(string)] = svcWithNonVersionKey
+ svcKeys = append(svcKeys, key)
+ svcIDs = append(svcIDs, keyValue.Value.(string))
}
- result.Services.Count = int64(len(svcWithNonVersion))
- result.Apps.Count = int64(len(app))
+ svcIDToNonVerKey := datasource.SetStaticServices(result, svcKeys,
svcIDs, withShared)
- respGetInstanceCountByDomain := make(chan
GetInstanceCountByDomainResponse, 1)
+ respGetInstanceCountByDomain := make(chan
datasource.GetInstanceCountByDomainResponse, 1)
gopool.Go(func(_ context.Context) {
getInstanceCountByDomain(ctx, svcIDToNonVerKey,
respGetInstanceCountByDomain)
})
@@ -425,30 +409,23 @@ func statistics(ctx context.Context, withShared bool)
(*pb.Statistics, error) {
return nil, err
}
- onlineServices := make(map[string]struct{}, respSvc.Count)
+ var instIDs []string
for _, keyValue := range respIns.Kvs {
serviceID, _, _ := path.GetInfoFromInstKV(keyValue.Key)
- key, ok := svcIDToNonVerKey[serviceID]
- if !ok {
- continue
- }
- result.Instances.Count++
- if _, ok := onlineServices[key]; !ok {
- onlineServices[key] = struct{}{}
- }
+ instIDs = append(instIDs, serviceID)
}
- result.Services.OnlineCount = int64(len(onlineServices))
+ datasource.SetStaticInstances(result, svcIDToNonVerKey, instIDs)
data := <-respGetInstanceCountByDomain
close(respGetInstanceCountByDomain)
- if data.err != nil {
- return nil, data.err
+ if data.Err != nil {
+ return nil, data.Err
}
- result.Instances.CountByDomain = data.countByDomain
+ result.Instances.CountByDomain = data.CountByDomain
return result, nil
}
-func getInstanceCountByDomain(ctx context.Context, svcIDToNonVerKey
map[string]string, resp chan GetInstanceCountByDomainResponse) {
+func getInstanceCountByDomain(ctx context.Context, svcIDToNonVerKey
map[string]string, resp chan datasource.GetInstanceCountByDomainResponse) {
domainID := util.ParseDomain(ctx)
key := path.GetInstanceRootKey(domainID) + "/"
instOpts := append([]client.PluginOpOption{},
@@ -456,8 +433,8 @@ func getInstanceCountByDomain(ctx context.Context,
svcIDToNonVerKey map[string]s
client.WithPrefix(),
client.WithKeyOnly())
respIns, err := kv.Store().Instance().Search(ctx, instOpts...)
- ret := GetInstanceCountByDomainResponse{
- err: err,
+ ret := datasource.GetInstanceCountByDomainResponse{
+ Err: err,
}
if err != nil {
@@ -469,7 +446,7 @@ func getInstanceCountByDomain(ctx context.Context,
svcIDToNonVerKey map[string]s
if !ok {
continue
}
- ret.countByDomain++
+ ret.CountByDomain++
}
}
diff --git a/datasource/mongo/client/errortypes.go
b/datasource/mongo/client/errortypes.go
index c70ffbb..9d7311a 100644
--- a/datasource/mongo/client/errortypes.go
+++ b/datasource/mongo/client/errortypes.go
@@ -15,7 +15,15 @@
package client
-import "go.mongodb.org/mongo-driver/mongo"
+import (
+ "errors"
+
+ "go.mongodb.org/mongo-driver/mongo"
+)
+
+var (
+ ErrNoDocuments = errors.New("no doc found")
+)
const (
DuplicateKey = 11000
@@ -34,3 +42,7 @@ func IsDuplicateKey(err error) bool {
}
return false
}
+
+func IsNoneDoc(err error) bool {
+ return err == ErrNoDocuments
+}
diff --git a/datasource/mongo/client/mongo.go b/datasource/mongo/client/mongo.go
index 4be189a..aac7be7 100644
--- a/datasource/mongo/client/mongo.go
+++ b/datasource/mongo/client/mongo.go
@@ -48,6 +48,11 @@ type MongoClient struct {
goroutine *gopool.Pool
}
+type MongoOperation struct {
+ Table string
+ Models []mongo.WriteModel
+}
+
func GetMongoClient() *MongoClient {
return mc
}
@@ -135,6 +140,14 @@ func (mc *MongoClient) newClient(ctx context.Context) (err
error) {
return nil
}
+func (mc *MongoClient) CreateIndexes(ctx context.Context, Table string,
indexes []mongo.IndexModel) error {
+ _, err := mc.db.Collection(Table).Indexes().CreateMany(ctx, indexes)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
func (mc *MongoClient) Insert(ctx context.Context, Table string, document
interface{}, opts ...*options.InsertOneOptions) (*mongo.InsertOneResult, error)
{
return mc.db.Collection(Table).InsertOne(ctx, document, opts...)
}
@@ -187,6 +200,16 @@ func (mc *MongoClient) StartSession(ctx context.Context)
(mongo.Session, error)
return mc.client.StartSession()
}
+func (mc *MongoClient) MultiTableBatchUpdate(ctx context.Context, opts
[]MongoOperation) error {
+ for _, op := range opts {
+ _, err := mc.BatchUpdate(ctx, op.Table, op.Models)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
func (mc *MongoClient) DocExist(ctx context.Context, table string, filter
bson.M) (bool, error) {
res, err := mc.FindOne(ctx, table, filter)
if err != nil {
@@ -205,7 +228,7 @@ func (mc *MongoClient) DocUpdate(ctx context.Context, table
string, filter inter
}
if res.Err() != nil {
// means no doc find, if the operation is update,should return
err
- return res.Err()
+ return ErrNoDocuments
}
return nil
}
diff --git a/datasource/mongo/mongo.go b/datasource/mongo/mongo.go
index 0dc6870..fb607cc 100644
--- a/datasource/mongo/mongo.go
+++ b/datasource/mongo/mongo.go
@@ -18,12 +18,17 @@
package mongo
import (
+ "context"
+
"github.com/apache/servicecomb-service-center/datasource"
"github.com/apache/servicecomb-service-center/datasource/mongo/client"
"github.com/apache/servicecomb-service-center/datasource/mongo/heartbeat"
"github.com/apache/servicecomb-service-center/pkg/log"
"github.com/apache/servicecomb-service-center/server/config"
"github.com/go-chassis/go-chassis/v2/storage"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "go.mongodb.org/mongo-driver/x/bsonx"
)
func init() {
@@ -39,7 +44,6 @@ type DataSource struct {
func NewDataSource(opts datasource.Options) (datasource.DataSource, error) {
// TODO: construct a reasonable DataSource instance
- log.Warn("data source enable mongo mode")
inst := &DataSource{
SchemaEditable: opts.SchemaEditable,
@@ -64,6 +68,10 @@ func (ds *DataSource) initialize() error {
if err != nil {
return err
}
+ err = ds.createIndexes()
+ if err != nil {
+ return err
+ }
return nil
}
@@ -88,3 +96,25 @@ func (ds *DataSource) initClient() error {
return nil
}
}
+
+//{Key: StringBuilder([]string{ColumnServiceInfo, ColumnAlias}), Value:
bsonx.Int32(1)}
+func (ds *DataSource) createIndexes() (err error) {
+ err = client.GetMongoClient().CreateIndexes(context.TODO(),
CollectionService, []mongo.IndexModel{{
+ Keys: bsonx.Doc{{Key:
StringBuilder([]string{ColumnServiceInfo, ColumnServiceID}), Value:
bsonx.Int32(1)}},
+ Options: options.Index().SetUnique(true),
+ }, {
+ Keys: bsonx.Doc{{Key:
StringBuilder([]string{ColumnServiceInfo, ColumnAppID}), Value:
bsonx.Int32(1)}, {Key: StringBuilder([]string{ColumnServiceInfo,
ColumnServiceName}), Value: bsonx.Int32(1)}, {Key:
StringBuilder([]string{ColumnServiceInfo, ColumnEnv}), Value: bsonx.Int32(1)},
{Key: StringBuilder([]string{ColumnServiceInfo, ColumnVersion}), Value:
bsonx.Int32(1)}},
+ Options: options.Index().SetUnique(true),
+ }})
+ if err != nil {
+ return
+ }
+ err = client.GetMongoClient().CreateIndexes(context.TODO(),
CollectionInstance, []mongo.IndexModel{{
+ Keys: bsonx.Doc{{Key:
StringBuilder([]string{ColumnInstanceInfo, ColumnInstanceID}), Value:
bsonx.Int32(1)}},
+ Options: options.Index().SetUnique(true),
+ }, {Keys: bsonx.Doc{{Key: StringBuilder([]string{ColumnInstanceID,
ColumnServiceID}), Value: bsonx.Int32(1)}}}})
+ if err != nil {
+ return
+ }
+ return
+}
diff --git a/datasource/mongo/ms.go b/datasource/mongo/ms.go
index 106cfca..3ecc494 100644
--- a/datasource/mongo/ms.go
+++ b/datasource/mongo/ms.go
@@ -27,6 +27,9 @@ import (
"strings"
"time"
+ "github.com/apache/servicecomb-service-center/server/plugin/quota"
+ "go.mongodb.org/mongo-driver/mongo"
+
"github.com/go-chassis/cari/discovery"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
@@ -44,9 +47,11 @@ import (
func (ds *DataSource) RegisterService(ctx context.Context, request
*discovery.CreateServiceRequest) (
*discovery.CreateServiceResponse, error) {
service := request.Service
-
+ remoteIP := util.GetIPFromContext(ctx)
domain := util.ParseDomain(ctx)
project := util.ParseProject(ctx)
+ serviceFlag := util.StringJoin([]string{
+ service.Environment, service.AppId, service.ServiceName,
service.Version}, "/")
//todo add quota check
requestServiceID := service.ServiceId
@@ -54,45 +59,48 @@ func (ds *DataSource) RegisterService(ctx context.Context,
request *discovery.Cr
ctx = util.SetContext(ctx, uuid.ContextKey,
util.StringJoin([]string{domain, project, service.Environment, service.AppId,
service.ServiceName, service.Alias, service.Version}, "/"))
service.ServiceId = uuid.Generator().GetServiceID(ctx)
}
+ service.Timestamp = strconv.FormatInt(time.Now().Unix(), 10)
+ service.ModTimestamp = service.Timestamp
// the service unique index in table is
(serviceId,serviceEnv,serviceAppid,servicename,serviceAlias,serviceVersion)
- existID, err := ServiceExistID(ctx, service.ServiceId)
- if err != nil {
- return &discovery.CreateServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Check service exist failed"),
- }, err
- }
- exist, err := ServiceExist(ctx, &discovery.MicroServiceKey{
- Environment: service.Environment,
- AppId: service.AppId,
- ServiceName: service.ServiceName,
- Alias: service.Alias,
- Version: service.Version,
- })
- if err != nil {
- return &discovery.CreateServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Check service exist failed"),
- }, err
- }
- if existID || exist {
- return &discovery.CreateServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrServiceAlreadyExists, "ServiceID conflict
or found the same service."),
- }, nil
- }
insertRes, err := client.GetMongoClient().Insert(ctx,
CollectionService, &Service{Domain: domain, Project: project, ServiceInfo:
service})
if err != nil {
if client.IsDuplicateKey(err) {
+ if len(requestServiceID) == 0 {
+ serviceIDInner, err := GetServiceID(ctx,
&discovery.MicroServiceKey{
+ Environment: service.Environment,
+ AppId: service.AppId,
+ ServiceName: service.ServiceName,
+ Version: service.Version,
+ })
+ if err != nil {
+ return &discovery.CreateServiceResponse{
+ Response:
discovery.CreateResponse(discovery.ErrUnavailableBackend, err.Error()),
+ }, err
+ }
+ if len(serviceIDInner) != 0 {
+ log.Warn(fmt.Sprintf("create
micro-service[%s][%s] failed, service already exists, operator: %s",
+ serviceIDInner, serviceFlag,
remoteIP))
+ return &discovery.CreateServiceResponse{
+ Response:
discovery.CreateResponse(discovery.ResponseSuccess, "register service
successfully"),
+ ServiceId: serviceIDInner,
+ }, nil
+ }
+ }
+ log.Warn(fmt.Sprintf("create micro-service[%s] failed,
service already exists, operator: %s",
+ serviceFlag, remoteIP))
return &discovery.CreateServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrServiceAlreadyExists, "ServiceID or
ServiceInfo conflict."),
+ Response:
discovery.CreateResponse(discovery.ErrServiceAlreadyExists,
+ "ServiceID conflict or found the same
service with different id."),
}, nil
}
+ log.Error(fmt.Sprintf("create micro-service[%s] failed, service
already exists, operator: %s",
+ serviceFlag, remoteIP), err)
return &discovery.CreateServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Register service failed."),
+ Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
}, err
}
- remoteIP := util.GetIPFromContext(ctx)
- log.Info(fmt.Sprintf("create micro-service[%s][%s]
successfully,operator: %s",
- service.ServiceId, insertRes.InsertedID, remoteIP))
+ log.Info(fmt.Sprintf("create micro-service[%s][%s]
successfully,operator: %s", service.ServiceId, insertRes.InsertedID, remoteIP))
return &discovery.CreateServiceResponse{
Response: discovery.CreateResponse(discovery.ResponseSuccess,
"Register service successfully"),
@@ -139,7 +147,7 @@ func (ds *DataSource) GetApplications(ctx context.Context,
request *discovery.Ge
l := len(services)
if l == 0 {
return &discovery.GetAppsResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "get services data failed."),
+ Response:
discovery.CreateResponse(discovery.ResponseSuccess, "Get all applications
successfully."),
}, nil
}
apps := make([]string, 0, l)
@@ -235,54 +243,18 @@ func (ds *DataSource) ExistService(ctx context.Context,
request *discovery.GetEx
}
func (ds *DataSource) UnregisterService(ctx context.Context, request
*discovery.DeleteServiceRequest) (*discovery.DeleteServiceResponse, error) {
- exist, err := ServiceExistID(ctx, request.ServiceId)
+ res, err := ds.DelServicePri(ctx, request.ServiceId, request.Force)
if err != nil {
return &discovery.DeleteServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Delete service failed,failed
to get service."),
- }, err
- }
- if !exist {
- return &discovery.DeleteServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, "Delete service
failed,service not exist."),
- }, nil
- }
- session, err := client.GetMongoClient().StartSession(ctx)
- if err != nil {
- return &discovery.DeleteServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "DelService failed to create
session."),
- }, err
- }
- if err = session.StartTransaction(); err != nil {
- return &discovery.DeleteServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "DelService failed to start
session."),
- }, err
- }
- defer session.EndSession(ctx)
- //todo delete instance,tags,schemas...
- res, err := DelServicePri(ctx, request.ServiceId, request.Force)
- if err != nil {
- errAbort := session.AbortTransaction(ctx)
- if errAbort != nil {
- return &discovery.DeleteServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Txn delete service abort
failed."),
- }, errAbort
- }
- return &discovery.DeleteServiceResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, "Delete service failed"),
}, err
}
- errCommit := session.CommitTransaction(ctx)
- if errCommit != nil {
- return &discovery.DeleteServiceResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Txn delete service commit
failed."),
- }, errCommit
- }
return &discovery.DeleteServiceResponse{
Response: res,
}, nil
}
-func DelServicePri(ctx context.Context, serviceID string, force bool)
(*discovery.Response, error) {
+func (ds *DataSource) DelServicePri(ctx context.Context, serviceID string,
force bool) (*discovery.Response, error) {
remoteIP := util.GetIPFromContext(ctx)
title := "delete"
if force {
@@ -306,42 +278,41 @@ func DelServicePri(ctx context.Context, serviceID string,
force bool) (*discover
}
// 强制删除,则与该服务相关的信息删除,非强制删除:
如果作为该被依赖(作为provider,提供服务,且不是只存在自依赖)或者存在实例,则不能删除
if !force {
- log.Info("force delete,should del instance...")
//todo wait for dep interface
- }
- filter := GeneratorServiceFilter(ctx, serviceID)
- //todo del instances
- tables := []string{CollectionService, CollectionSchema, CollectionRule}
- for _, col := range tables {
- _, err := client.GetMongoClient().Delete(ctx, col, filter)
+ instancesExist, err := client.GetMongoClient().DocExist(ctx,
CollectionInstance, bson.M{StringBuilder([]string{ColumnInstanceInfo,
ColumnServiceID}): serviceID})
if err != nil {
- return discovery.CreateResponse(discovery.ErrInternal,
err.Error()), err
+ log.Error(fmt.Sprintf("delete micro-service[%s] failed,
get instances number failed, operator: %s",
+ serviceID, remoteIP), err)
+ return
discovery.CreateResponse(discovery.ErrUnavailableBackend, err.Error()), err
}
+ if instancesExist {
+ log.Error(fmt.Sprintf("delete micro-service[%s] failed,
service deployed instances, operator: %s",
+ serviceID, remoteIP), nil)
+ return
discovery.CreateResponse(discovery.ErrDeployedInstance, "Can not delete the
service deployed instance(s)."), err
+ }
+
}
- return discovery.CreateResponse(discovery.ResponseSuccess, "Unregister
service successfully."), nil
+ //todo del dep
+ schemaOps := client.MongoOperation{Table: CollectionSchema, Models:
[]mongo.WriteModel{mongo.NewDeleteManyModel().SetFilter(bson.M{ColumnServiceID:
serviceID})}}
+ rulesOps := client.MongoOperation{Table: CollectionRule, Models:
[]mongo.WriteModel{mongo.NewDeleteManyModel().SetFilter(bson.M{ColumnServiceID:
serviceID})}}
+ instanceOps := client.MongoOperation{Table: CollectionInstance, Models:
[]mongo.WriteModel{mongo.NewDeleteManyModel().SetFilter(bson.M{StringBuilder([]string{ColumnInstanceInfo,
ColumnServiceID}): serviceID})}}
+ serviceOps := client.MongoOperation{Table: CollectionService, Models:
[]mongo.WriteModel{mongo.NewDeleteOneModel().SetFilter(bson.M{StringBuilder([]string{ColumnServiceInfo,
ColumnServiceID}): serviceID})}}
+ err = client.GetMongoClient().MultiTableBatchUpdate(ctx,
[]client.MongoOperation{schemaOps, rulesOps, instanceOps, serviceOps})
+ if err != nil {
+ log.Error(fmt.Sprintf("micro-service[%s] failed, operator: %s",
serviceID, remoteIP), err)
+ return
discovery.CreateResponse(discovery.ErrUnavailableBackend, err.Error()), err
+ }
+ return discovery.CreateResponse(discovery.ResponseSuccess, "Unregister
service successfully."), nil
}
func (ds *DataSource) UpdateService(ctx context.Context, request
*discovery.UpdateServicePropsRequest) (
*discovery.UpdateServicePropsResponse, error) {
-
- exist, err := ServiceExistID(ctx, request.ServiceId)
- if err != nil {
- return &discovery.UpdateServicePropsResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "UpdateService failed,failed to
get service."),
- }, err
- }
- if !exist {
- return &discovery.UpdateServicePropsResponse{
- Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, "UpdateService
failed,service not exist."),
- }, nil
- }
-
updateData := bson.M{
"$set": bson.M{
StringBuilder([]string{ColumnServiceInfo,
ColumnModTime}): strconv.FormatInt(time.Now().Unix(), 10),
StringBuilder([]string{ColumnServiceInfo,
ColumnProperty}): request.Properties}}
- err = UpdateService(ctx, GeneratorServiceFilter(ctx,
request.ServiceId), updateData)
+ err := UpdateService(ctx, GeneratorServiceFilter(ctx,
request.ServiceId), updateData)
if err != nil {
log.Error(fmt.Sprintf("update service %s properties failed,
update mongo failed", request.ServiceId), err)
return &discovery.UpdateServicePropsResponse{
@@ -355,7 +326,20 @@ func (ds *DataSource) UpdateService(ctx context.Context,
request *discovery.Upda
func (ds *DataSource) GetDeleteServiceFunc(ctx context.Context, serviceID
string, force bool,
serviceRespChan chan<- *discovery.DelServicesRspInfo)
func(context.Context) {
- return func(_ context.Context) {}
+ return func(_ context.Context) {
+ serviceRst := &discovery.DelServicesRspInfo{
+ ServiceId: serviceID,
+ ErrMessage: "",
+ }
+ resp, err := ds.DelServicePri(ctx, serviceID, force)
+ if err != nil {
+ serviceRst.ErrMessage = err.Error()
+ } else if resp.GetCode() != discovery.ResponseSuccess {
+ serviceRst.ErrMessage = resp.GetMessage()
+ }
+
+ serviceRespChan <- serviceRst
+ }
}
func (ds *DataSource) GetServiceDetail(ctx context.Context, request
*discovery.GetServiceRequest) (
@@ -372,7 +356,12 @@ func (ds *DataSource) GetServiceDetail(ctx
context.Context, request *discovery.G
}, nil
}
svc := mgSvc.ServiceInfo
- versions, err := GetServicesVersions(ctx, bson.M{})
+ key := &discovery.MicroServiceKey{
+ Environment: svc.Environment,
+ AppId: svc.AppId,
+ ServiceName: svc.ServiceName,
+ }
+ versions, err := GetServicesVersions(ctx,
GeneratorServiceVersionsFilter(ctx, key))
if err != nil {
log.Error(fmt.Sprintf("get service %s %s %s all versions
failed", svc.Environment, svc.AppId, svc.ServiceName), err)
return &discovery.GetServiceDetailResponse{
@@ -411,7 +400,22 @@ func (ds *DataSource) GetServicesInfo(ctx context.Context,
request *discovery.Ge
options = append(options, opt)
}
}
- //todo add get statistics info
+ var st *discovery.Statistics
+ if _, ok := optionMap["statistics"]; ok {
+ var err error
+ st, err = statistics(ctx, request.WithShared)
+ if err != nil {
+ return &discovery.GetServicesInfoResponse{
+ Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
+ }, err
+ }
+ if len(optionMap) == 1 {
+ return &discovery.GetServicesInfoResponse{
+ Response:
discovery.CreateResponse(discovery.ResponseSuccess, "Statistics successfully."),
+ Statistics: st,
+ }, nil
+ }
+ }
services, err := GetMongoServices(ctx, bson.M{})
if err != nil {
log.Error("get all services by domain failed", err)
@@ -452,6 +456,7 @@ func (ds *DataSource) GetServicesInfo(ctx context.Context,
request *discovery.Ge
}
func (ds *DataSource) AddTags(ctx context.Context, request
*discovery.AddServiceTagsRequest) (*discovery.AddServiceTagsResponse, error) {
+ remoteIP := util.GetIPFromContext(ctx)
service, err := GetService(ctx, GeneratorServiceFilter(ctx,
request.ServiceId))
if err != nil {
log.Error(fmt.Sprintf("failed to add tags for service %s for
get service failed", request.ServiceId), err)
@@ -462,9 +467,21 @@ func (ds *DataSource) AddTags(ctx context.Context, request
*discovery.AddService
if service == nil {
return &discovery.AddServiceTagsResponse{Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, "Service not exist")},
nil
}
- //todo add quto check
- dataTags := service.Tags
tags := request.Tags
+ res := quota.NewApplyQuotaResource(quota.TagQuotaType,
util.ParseDomainProject(ctx), request.ServiceId, int64(len(tags)))
+ rst := quota.Apply(ctx, res)
+ errQuota := rst.Err
+ if errQuota != nil {
+ log.Error(fmt.Sprintf("add service[%s]'s tags %v failed,
operator: %s", request.ServiceId, tags, remoteIP), errQuota)
+ response := &discovery.AddServiceTagsResponse{
+ Response: discovery.CreateResponseWithSCErr(errQuota),
+ }
+ if errQuota.InternalError() {
+ return response, errQuota
+ }
+ return response, nil
+ }
+ dataTags := service.Tags
for key, value := range dataTags {
if _, ok := tags[key]; ok {
continue
@@ -593,38 +610,64 @@ func (ds *DataSource) GetSchema(ctx context.Context,
request *discovery.GetSchem
Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, "GetSchema service does
not exist."),
}, nil
}
- Schema, err := GetSchema(ctx, GeneratorSchemaFilter(ctx,
request.ServiceId, request.SchemaId))
+ schema, err := GetSchema(ctx, GeneratorSchemaFilter(ctx,
request.ServiceId, request.SchemaId))
if err != nil {
return &discovery.GetSchemaResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, "GetSchema failed from
mongodb."),
}, nil
}
+ if schema == nil {
+ return &discovery.GetSchemaResponse{
+ Response:
discovery.CreateResponse(discovery.ErrSchemaNotExists, "Do not have this schema
info."),
+ }, nil
+ }
return &discovery.GetSchemaResponse{
Response:
discovery.CreateResponse(discovery.ResponseSuccess, "Get schema info
successfully."),
- Schema: Schema.SchemaInfo,
- SchemaSummary: Schema.SchemaSummary,
+ Schema: schema.SchemaInfo,
+ SchemaSummary: schema.SchemaSummary,
}, nil
}
func (ds *DataSource) GetAllSchemas(ctx context.Context, request
*discovery.GetAllSchemaRequest) (*discovery.GetAllSchemaResponse, error) {
- exist, err := ServiceExistID(ctx, request.ServiceId)
+ svc, err := GetService(ctx, GeneratorServiceFilter(ctx,
request.ServiceId))
if err != nil {
+ log.Error(fmt.Sprintf("get service[%s] all schemas failed, get
service failed", request.ServiceId), err)
return &discovery.GetAllSchemaResponse{
- Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, "GetAllSchemas failed
for get service failed"),
- }, nil
+ Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
+ }, err
}
- if !exist {
+ if svc == nil {
return &discovery.GetAllSchemaResponse{
Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, "GetAllSchemas failed
for service not exist"),
}, nil
}
-
- schemas, err := GetSchemas(ctx, GeneratorServiceFilter(ctx,
request.ServiceId))
- if err != nil {
+ schemasList := svc.ServiceInfo.Schemas
+ if len(schemasList) == 0 {
return &discovery.GetAllSchemaResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "GetAllSchemas failed for get
schemas failed"),
+ Response:
discovery.CreateResponse(discovery.ResponseSuccess, "Do not have this schema
info."),
+ Schemas: []*discovery.Schema{},
}, nil
}
+ schemas := make([]*discovery.Schema, 0, len(schemasList))
+ for _, schemaID := range schemasList {
+ tempSchema := &discovery.Schema{}
+ tempSchema.SchemaId = schemaID
+ schema, err := GetSchema(ctx, GeneratorSchemaFilter(ctx,
request.ServiceId, schemaID))
+ if err != nil {
+ return &discovery.GetAllSchemaResponse{
+ Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
+ }, err
+ }
+ if schema == nil {
+ schemas = append(schemas, tempSchema)
+ continue
+ }
+ tempSchema.Summary = schema.SchemaSummary
+ if request.WithSchema {
+ tempSchema.Schema = schema.SchemaInfo
+ }
+ schemas = append(schemas, tempSchema)
+ }
return &discovery.GetAllSchemaResponse{
Response: discovery.CreateResponse(discovery.ResponseSuccess,
"Get all schema info successfully."),
Schemas: schemas,
@@ -675,10 +718,15 @@ func (ds *DataSource) DeleteSchema(ctx context.Context,
request *discovery.Delet
}, nil
}
filter := GeneratorSchemaFilter(ctx, request.ServiceId,
request.SchemaId)
- _, err = client.GetMongoClient().Delete(ctx, CollectionSchema, filter)
+ res, err := client.GetMongoClient().DocDelete(ctx, CollectionSchema,
filter)
if err != nil {
return &discovery.DeleteSchemaResponse{
Response:
discovery.CreateResponse(discovery.ErrUnavailableBackend, "DeleteSchema failed
for delete schema failed."),
+ }, err
+ }
+ if !res {
+ return &discovery.DeleteSchemaResponse{
+ Response:
discovery.CreateResponse(discovery.ErrSchemaNotExists, "DeleteSchema failed for
schema not exist."),
}, nil
}
return &discovery.DeleteSchemaResponse{
@@ -695,36 +743,16 @@ func (ds *DataSource) ModifySchema(ctx context.Context,
request *discovery.Modif
Summary: request.Summary,
Schema: request.Schema,
}
- session, err := client.GetMongoClient().StartSession(ctx)
+ err := ds.modifySchema(ctx, request.ServiceId, &schema)
if err != nil {
- return &discovery.ModifySchemaResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "ModifySchema failed to create
session."),
- }, err
- }
- if err = session.StartTransaction(); err != nil {
- return &discovery.ModifySchemaResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "ModifySchema failed to start
session."),
- }, err
- }
- defer session.EndSession(ctx)
- err = ds.modifySchema(ctx, request.ServiceId, &schema)
- if err != nil {
- log.Error(fmt.Sprintf("modify schema %s %s failed, operator
%s", serviceID, schemaID, remoteIP), err)
- errAbort := session.AbortTransaction(ctx)
- if errAbort != nil {
- return &discovery.ModifySchemaResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Txn ModifySchema Abort
failed."),
- }, errAbort
+ log.Error(fmt.Sprintf("modify schema[%s/%s] failed, operator:
%s", serviceID, schemaID, remoteIP), err)
+ resp := &discovery.ModifySchemaResponse{
+ Response: discovery.CreateResponseWithSCErr(err),
}
- return &discovery.ModifySchemaResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Txn ModifySchema failed."),
- }, err
- }
- err = session.CommitTransaction(ctx)
- if err != nil {
- return &discovery.ModifySchemaResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Txn ModifySchema
CommitTransaction failed."),
- }, err
+ if err.InternalError() {
+ return resp, err
+ }
+ return resp, nil
}
log.Info(fmt.Sprintf("modify schema[%s/%s] successfully, operator: %s",
serviceID, schemaID, remoteIP))
return &discovery.ModifySchemaResponse{
@@ -740,33 +768,15 @@ func (ds *DataSource) ModifySchemas(ctx context.Context,
request *discovery.Modi
if svc == nil {
return &discovery.ModifySchemasResponse{Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, "Service not exist")},
nil
}
- session, err := client.GetMongoClient().StartSession(ctx)
- if err != nil {
- return &discovery.ModifySchemasResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "ModifySchemas failed to start
session"),
- }, err
- }
- if err = session.StartTransaction(); err != nil {
- return &discovery.ModifySchemasResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "ModifySchemas failed to start
session"),
- }, err
- }
- defer session.EndSession(ctx)
- err = ds.modifySchemas(ctx, svc.ServiceInfo, request.Schemas)
- if err != nil {
- errAbort := session.AbortTransaction(ctx)
- if errAbort != nil {
- return &discovery.ModifySchemasResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Txn ModifySchemas Abort
failed."),
- }, errAbort
+ respErr := ds.modifySchemas(ctx, svc.ServiceInfo, request.Schemas)
+ if respErr != nil {
+ resp := &discovery.ModifySchemasResponse{
+ Response: discovery.CreateResponseWithSCErr(respErr),
}
- return &discovery.ModifySchemasResponse{Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error())}, err
- }
- err = session.CommitTransaction(ctx)
- if err != nil {
- return &discovery.ModifySchemasResponse{
- Response:
discovery.CreateResponse(discovery.ErrInternal, "Txn ModifySchemas
CommitTransaction failed."),
- }, err
+ if respErr.InternalError() {
+ return resp, err
+ }
+ return resp, nil
}
return &discovery.ModifySchemasResponse{
Response: discovery.CreateResponse(discovery.ResponseSuccess,
"modify schemas info success"),
@@ -774,90 +784,33 @@ func (ds *DataSource) ModifySchemas(ctx context.Context,
request *discovery.Modi
}
-func (ds *DataSource) modifySchema(ctx context.Context, serviceID string,
schema *discovery.Schema) *discovery.Error {
- remoteIP := util.GetIPFromContext(ctx)
- svc, err := GetService(ctx, GeneratorServiceFilter(ctx, serviceID))
- if err != nil {
- return discovery.NewError(discovery.ErrInternal, err.Error())
- }
- if svc == nil {
- return discovery.NewError(discovery.ErrServiceNotExists,
"service does not exist.")
- }
- microservice := svc.ServiceInfo
- var isExist bool
- for _, sid := range microservice.Schemas {
- if sid == schema.SchemaId {
- isExist = true
- break
- }
- }
- var newSchemas []string
- if !ds.isSchemaEditable(microservice) {
- if len(microservice.Schemas) != 0 && !isExist {
- return
discovery.NewError(discovery.ErrUndefinedSchemaID, "non-existent schemaID can't
be added request "+discovery.ENV_PROD)
- }
- respSchema, err := GetSchema(ctx, GeneratorSchemaFilter(ctx,
serviceID, schema.SchemaId))
- if err != nil {
- return
discovery.NewError(discovery.ErrUnavailableBackend, err.Error())
- }
- if schema != nil {
- if len(schema.Summary) == 0 {
- log.Error(fmt.Sprintf("modify schema %s %s
failed, get schema summary failed, operator: %s",
- serviceID, schema.SchemaId, remoteIP),
err)
- return
discovery.NewError(discovery.ErrUnavailableBackend, err.Error())
- }
- if len(respSchema.SchemaSummary) != 0 {
- log.Error(fmt.Sprintf("mode, schema %s %s
already exist, can not be changed, operator: %s",
- serviceID, schema.SchemaId, remoteIP),
err)
- return
discovery.NewError(discovery.ErrModifySchemaNotAllow, "schema already exist,
can not be changed request "+discovery.ENV_PROD)
- }
- }
- if len(microservice.Schemas) == 0 {
- copy(newSchemas, microservice.Schemas)
- newSchemas = append(newSchemas, schema.SchemaId)
- }
- } else {
- if !isExist {
- copy(newSchemas, microservice.Schemas)
- newSchemas = append(newSchemas, schema.SchemaId)
- }
- }
- if len(newSchemas) != len(microservice.Schemas) {
-
- updateData := bson.M{StringBuilder([]string{ColumnServiceInfo,
ColumnSchemas}): newSchemas}
- err := UpdateService(ctx, GeneratorServiceFilter(ctx,
serviceID), bson.M{"$set": updateData})
- if err != nil {
- return discovery.NewError(discovery.ErrInternal,
err.Error())
- }
- }
- newSchema := bson.M{"$set": bson.M{ColumnSchemaInfo: schema.Schema,
ColumnSchemaSummary: schema.Summary}}
- err = UpdateSchema(ctx, GeneratorSchemaFilter(ctx, serviceID,
schema.SchemaId), newSchema, options.FindOneAndUpdate().SetUpsert(true))
- if err != nil {
- return discovery.NewError(discovery.ErrInternal, err.Error())
- }
- return nil
-}
-
func (ds *DataSource) modifySchemas(ctx context.Context, service
*discovery.MicroService, schemas []*discovery.Schema) *discovery.Error {
+ domain := util.ParseDomain(ctx)
+ project := util.ParseProject(ctx)
remoteIP := util.GetIPFromContext(ctx)
+
serviceID := service.ServiceId
- schemasFromDatabase, err := GetSchemas(ctx, GeneratorServiceFilter(ctx,
serviceID))
+ schemasFromDatabase, err := GetSchemas(ctx, bson.M{ColumnServiceID:
serviceID})
if err != nil {
log.Error(fmt.Sprintf("modify service %s schemas failed, get
schemas failed, operator: %s", serviceID, remoteIP), err)
return discovery.NewError(discovery.ErrUnavailableBackend,
err.Error())
}
+
needUpdateSchemas, needAddSchemas, needDeleteSchemas, nonExistSchemaIds
:=
datasource.SchemasAnalysis(schemas, schemasFromDatabase,
service.Schemas)
+
+ var schemasOps []mongo.WriteModel
+ var serviceOps []mongo.WriteModel
if !ds.isSchemaEditable(service) {
if len(service.Schemas) == 0 {
- //todo add quota check
- updateData :=
bson.M{StringBuilder([]string{ColumnServiceInfo, ColumnSchemas}):
nonExistSchemaIds}
- err := UpdateService(ctx, GeneratorServiceFilter(ctx,
serviceID), bson.M{"$set": updateData})
- if err != nil {
- log.Error(fmt.Sprintf("modify service %s
schemas failed, update service.Schemas failed, operator: %s",
- serviceID, remoteIP), err)
- return
discovery.NewError(discovery.ErrInternal, err.Error())
+ res :=
quota.NewApplyQuotaResource(quota.SchemaQuotaType,
util.ParseDomainProject(ctx), serviceID, int64(len(nonExistSchemaIds)))
+ rst := quota.Apply(ctx, res)
+ errQuota := rst.Err
+ if errQuota != nil {
+ log.Error(fmt.Sprintf("modify service[%s]
schemas failed, operator: %s", serviceID, remoteIP), errQuota)
+ return errQuota
}
+ serviceOps = append(serviceOps,
mongo.NewUpdateOneModel().SetUpdate(bson.M{"$set":
bson.M{StringBuilder([]string{ColumnServiceInfo, ColumnSchemas}):
nonExistSchemaIds}}).SetFilter(GeneratorServiceFilter(ctx, serviceID)))
} else {
if len(nonExistSchemaIds) != 0 {
errInfo := fmt.Errorf("non-existent schemaIDs
%v", nonExistSchemaIds)
@@ -865,15 +818,12 @@ func (ds *DataSource) modifySchemas(ctx context.Context,
service *discovery.Micr
return
discovery.NewError(discovery.ErrUndefinedSchemaID, errInfo.Error())
}
for _, needUpdateSchema := range needUpdateSchemas {
- exist, err := SchemaExist(ctx, serviceID,
needUpdateSchema.SchemaId)
+ exist, err := SchemaSummaryExist(ctx,
serviceID, needUpdateSchema.SchemaId)
if err != nil {
return
discovery.NewError(discovery.ErrInternal, err.Error())
}
if !exist {
- err := UpdateSchema(ctx,
GeneratorSchemaFilter(ctx, serviceID, needUpdateSchema.SchemaId),
bson.M{"$set": bson.M{ColumnSchemaInfo: needUpdateSchema.Schema,
ColumnSchemaSummary: needUpdateSchema.Summary}},
options.FindOneAndUpdate().SetUpsert(true))
- if err != nil {
- return
discovery.NewError(discovery.ErrInternal, err.Error())
- }
+ schemasOps = append(schemasOps,
mongo.NewUpdateOneModel().SetFilter(GeneratorSchemaFilter(ctx, serviceID,
needUpdateSchema.SchemaId)).SetUpdate(bson.M{"$set": bson.M{ColumnSchemaInfo:
needUpdateSchema.Schema, ColumnSchemaSummary: needUpdateSchema.Summary}}))
} else {
log.Warn(fmt.Sprintf("schema[%s/%s] and
it's summary already exist, skip to update, operator: %s",
serviceID,
needUpdateSchema.SchemaId, remoteIP))
@@ -883,51 +833,139 @@ func (ds *DataSource) modifySchemas(ctx context.Context,
service *discovery.Micr
for _, schema := range needAddSchemas {
log.Info(fmt.Sprintf("add new schema[%s/%s], operator:
%s", serviceID, schema.SchemaId, remoteIP))
- err := UpdateSchema(ctx, GeneratorSchemaFilter(ctx,
serviceID, schema.SchemaId), bson.M{"$set": bson.M{ColumnSchemaInfo:
schema.Schema, ColumnSchemaSummary: schema.Summary}},
options.FindOneAndUpdate().SetUpsert(true))
+ schemasOps = append(schemasOps,
mongo.NewInsertOneModel().SetDocument(&Schema{
+ Domain: domain,
+ Project: project,
+ ServiceID: serviceID,
+ SchemaID: schema.SchemaId,
+ SchemaInfo: schema.Schema,
+ SchemaSummary: schema.Summary,
+ }))
+ }
+ } else {
+ quotaSize := len(needAddSchemas) - len(needDeleteSchemas)
+ if quotaSize > 0 {
+ res :=
quota.NewApplyQuotaResource(quota.SchemaQuotaType,
util.ParseDomainProject(ctx), serviceID, int64(quotaSize))
+ rst := quota.Apply(ctx, res)
+ err := rst.Err
if err != nil {
- return
discovery.NewError(discovery.ErrInternal, err.Error())
+ log.Error(fmt.Sprintf("modify service[%s]
schemas failed, operator: %s", serviceID, remoteIP), err)
+ return err
}
}
- } else {
-
var schemaIDs []string
for _, schema := range needAddSchemas {
log.Info(fmt.Sprintf("add new schema[%s/%s], operator:
%s", serviceID, schema.SchemaId, remoteIP))
- err := UpdateSchema(ctx, GeneratorSchemaFilter(ctx,
serviceID, schema.SchemaId), bson.M{"$set": bson.M{ColumnSchemaInfo:
schema.Schema, ColumnSchemaSummary: schema.Summary}},
options.FindOneAndUpdate().SetUpsert(true))
- if err != nil {
- return
discovery.NewError(discovery.ErrInternal, err.Error())
- }
+ schemasOps = append(schemasOps,
mongo.NewInsertOneModel().SetDocument(&Schema{
+ Domain: domain,
+ Project: project,
+ ServiceID: serviceID,
+ SchemaID: schema.SchemaId,
+ SchemaInfo: schema.Schema,
+ SchemaSummary: schema.Summary,
+ }))
schemaIDs = append(schemaIDs, schema.SchemaId)
}
for _, schema := range needUpdateSchemas {
log.Info(fmt.Sprintf("update schema[%s/%s], operator:
%s", serviceID, schema.SchemaId, remoteIP))
- err := UpdateSchema(ctx, GeneratorSchemaFilter(ctx,
serviceID, schema.SchemaId), bson.M{"$set": bson.M{ColumnSchemaInfo:
schema.Schema, ColumnSchemaSummary: schema.Summary}},
options.FindOneAndUpdate().SetUpsert(true))
- if err != nil {
- return
discovery.NewError(discovery.ErrInternal, err.Error())
- }
+ schemasOps = append(schemasOps,
mongo.NewUpdateOneModel().SetFilter(GeneratorSchemaFilter(ctx, serviceID,
schema.SchemaId)).SetUpdate(bson.M{"$set": bson.M{ColumnSchemaInfo:
schema.Schema, ColumnSchemaSummary: schema.Summary}}))
schemaIDs = append(schemaIDs, schema.SchemaId)
}
for _, schema := range needDeleteSchemas {
log.Info(fmt.Sprintf("delete non-existent
schema[%s/%s], operator: %s", serviceID, schema.SchemaId, remoteIP))
- err = DeleteSchema(ctx, GeneratorSchemaFilter(ctx,
serviceID, schema.SchemaId))
- if err != nil {
- return
discovery.NewError(discovery.ErrInternal, err.Error())
- }
+ schemasOps = append(schemasOps,
mongo.NewDeleteOneModel().SetFilter(GeneratorSchemaFilter(ctx, serviceID,
schema.SchemaId)))
}
- updateData := bson.M{StringBuilder([]string{ColumnServiceInfo,
ColumnSchemas}): schemaIDs}
- err := UpdateService(ctx, GeneratorServiceFilter(ctx,
serviceID), bson.M{"$set": updateData})
+ serviceOps = append(serviceOps,
mongo.NewUpdateOneModel().SetUpdate(bson.M{"$set":
bson.M{StringBuilder([]string{ColumnServiceInfo, ColumnSchemas}):
schemaIDs}}).SetFilter(GeneratorServiceFilter(ctx, serviceID)))
+ }
+ if len(schemasOps) > 0 {
+ _, err = client.GetMongoClient().BatchUpdate(ctx,
CollectionSchema, schemasOps)
+ if err != nil {
+ return discovery.NewError(discovery.ErrInternal,
err.Error())
+ }
+ }
+ if len(serviceOps) > 0 {
+ _, err = client.GetMongoClient().BatchUpdate(ctx,
CollectionService, serviceOps)
if err != nil {
- log.Error(fmt.Sprintf("modify service %s schemas
failed, update service.Schemas failed, operator: %s", serviceID, remoteIP), err)
return discovery.NewError(discovery.ErrInternal,
err.Error())
}
}
return nil
}
+// modifySchema will be modified in the following cases
+// 1.service have no relation --> update the schema && update the service
+// 2.service is editable && service have relation with the schema --> update
the shema
+// 3.service is editable && service have no relation with the schema -->
update the schema && update the service
+// 4.service can't edit && service have relation with the schema && schema
summary not exist --> update the schema
+func (ds *DataSource) modifySchema(ctx context.Context, serviceID string,
schema *discovery.Schema) *discovery.Error {
+ remoteIP := util.GetIPFromContext(ctx)
+ svc, err := GetService(ctx, GeneratorServiceFilter(ctx, serviceID))
+ if err != nil {
+ return discovery.NewError(discovery.ErrInternal, err.Error())
+ }
+ if svc == nil {
+ return discovery.NewError(discovery.ErrServiceNotExists,
"Service does not exist.")
+ }
+ microservice := svc.ServiceInfo
+ var isExist bool
+ for _, sid := range microservice.Schemas {
+ if sid == schema.SchemaId {
+ isExist = true
+ break
+ }
+ }
+ var newSchemas []string
+ if !ds.isSchemaEditable(microservice) {
+ if len(microservice.Schemas) != 0 && !isExist {
+ return
discovery.NewError(discovery.ErrUndefinedSchemaID, "Non-existent schemaID can't
be added request "+discovery.ENV_PROD)
+ }
+ respSchema, err := GetSchema(ctx, GeneratorSchemaFilter(ctx,
serviceID, schema.SchemaId))
+ if err != nil {
+ return
discovery.NewError(discovery.ErrUnavailableBackend, err.Error())
+ }
+ if respSchema != nil {
+ if len(schema.Summary) == 0 {
+ log.Error(fmt.Sprintf("modify schema %s %s
failed, get schema summary failed, operator: %s",
+ serviceID, schema.SchemaId, remoteIP),
err)
+ return
discovery.NewError(discovery.ErrModifySchemaNotAllow,
+ "schema already exist, can not be
changed request "+discovery.ENV_PROD)
+ }
+ if len(respSchema.SchemaSummary) != 0 {
+ log.Error(fmt.Sprintf("mode, schema %s %s
already exist, can not be changed, operator: %s",
+ serviceID, schema.SchemaId, remoteIP),
err)
+ return
discovery.NewError(discovery.ErrModifySchemaNotAllow, "schema already exist,
can not be changed request "+discovery.ENV_PROD)
+ }
+ }
+ if len(microservice.Schemas) == 0 {
+ copy(newSchemas, microservice.Schemas)
+ newSchemas = append(newSchemas, schema.SchemaId)
+ }
+ } else {
+ if !isExist {
+ copy(newSchemas, microservice.Schemas)
+ newSchemas = append(newSchemas, schema.SchemaId)
+ }
+ }
+ if len(newSchemas) != 0 {
+ updateData := bson.M{StringBuilder([]string{ColumnServiceInfo,
ColumnSchemas}): newSchemas}
+ err = UpdateService(ctx, GeneratorServiceFilter(ctx,
serviceID), bson.M{"$set": updateData})
+ if err != nil {
+ return discovery.NewError(discovery.ErrInternal,
err.Error())
+ }
+ }
+ newSchema := bson.M{"$set": bson.M{ColumnSchemaInfo: schema.Schema,
ColumnSchemaSummary: schema.Summary}}
+ err = UpdateSchema(ctx, GeneratorSchemaFilter(ctx, serviceID,
schema.SchemaId), newSchema, options.FindOneAndUpdate().SetUpsert(true))
+ if err != nil {
+ return discovery.NewError(discovery.ErrInternal, err.Error())
+ }
+ return nil
+}
+
func (ds *DataSource) AddRule(ctx context.Context, request
*discovery.AddServiceRulesRequest) (*discovery.AddServiceRulesResponse, error) {
+ remoteIP := util.GetIPFromContext(ctx)
exist, err := ServiceExistID(ctx, request.ServiceId)
if err != nil {
log.Error(fmt.Sprintf("failed to add rules for service %s for
get service failed", request.ServiceId), err)
@@ -938,7 +976,19 @@ func (ds *DataSource) AddRule(ctx context.Context, request
*discovery.AddService
if !exist {
return &discovery.AddServiceRulesResponse{Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, "Service does not
exist")}, nil
}
- //todo add quota check
+ res := quota.NewApplyQuotaResource(quota.RuleQuotaType,
util.ParseDomainProject(ctx), request.ServiceId, int64(len(request.Rules)))
+ rst := quota.Apply(ctx, res)
+ errQuota := rst.Err
+ if errQuota != nil {
+ log.Error(fmt.Sprintf("add service[%s] rule failed, operator:
%s", request.ServiceId, remoteIP), errQuota)
+ response := &discovery.AddServiceRulesResponse{
+ Response: discovery.CreateResponseWithSCErr(errQuota),
+ }
+ if errQuota.InternalError() {
+ return response, errQuota
+ }
+ return response, nil
+ }
rules, err := GetRules(ctx, request.ServiceId)
if err != nil {
return &discovery.AddServiceRulesResponse{
@@ -1034,25 +1084,33 @@ func (ds *DataSource) DeleteRule(ctx context.Context,
request *discovery.DeleteS
if !exist {
return &discovery.DeleteServiceRulesResponse{Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, "Service not exist")},
nil
}
+ var delRules []mongo.WriteModel
for _, ruleID := range request.RuleIds {
exist, err := RuleExist(ctx, GeneratorRuleFilter(ctx,
request.ServiceId, ruleID))
if err != nil {
return &discovery.DeleteServiceRulesResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
- }, nil
+ }, err
}
if !exist {
return &discovery.DeleteServiceRulesResponse{
Response:
discovery.CreateResponse(discovery.ErrRuleNotExists, "This rule does not
exist."),
}, nil
}
+ delRules = append(delRules,
mongo.NewDeleteOneModel().SetFilter(GeneratorRuleFilter(ctx, request.ServiceId,
ruleID)))
+ }
+ if len(delRules) > 0 {
+ _, err := client.GetMongoClient().BatchDelete(ctx,
CollectionRule, delRules)
+ if err != nil {
+ return &discovery.DeleteServiceRulesResponse{
+ Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
+ }, err
+ }
}
-
return &discovery.DeleteServiceRulesResponse{
Response: discovery.CreateResponse(discovery.ResponseSuccess,
"Delete service rules successfully."),
}, nil
}
-
func (ds *DataSource) UpdateRule(ctx context.Context, request
*discovery.UpdateServiceRuleRequest) (
*discovery.UpdateServiceRuleResponse, error) {
exist, err := ServiceExistID(ctx, request.ServiceId)
@@ -1179,18 +1237,19 @@ func GetServicesVersions(ctx context.Context, filter
interface{}) ([]string, err
}
var versions []string
for res.Next(ctx) {
- var tmp string
+ var tmp Service
err := res.Decode(&tmp)
if err != nil {
return nil, err
}
- versions = append(versions, tmp)
+ versions = append(versions, tmp.ServiceInfo.Version)
}
return versions, nil
}
func getServiceDetailUtil(ctx context.Context, mgs *Service, countOnly bool,
options []string) (*discovery.ServiceDetail, error) {
serviceDetail := new(discovery.ServiceDetail)
+ serviceID := mgs.ServiceInfo.ServiceId
if countOnly {
serviceDetail.Statics = new(discovery.Statistics)
}
@@ -1210,7 +1269,23 @@ func getServiceDetailUtil(ctx context.Context, mgs
*Service, countOnly bool, opt
}
serviceDetail.Rules = rules
case "instances":
- //todo wait instance interface
+ if countOnly {
+ instanceCount, err :=
GetInstanceCountOfOneService(ctx, serviceID)
+ if err != nil {
+ log.Error(fmt.Sprintf("get number of
service [%s]'s instances failed", serviceID), err)
+ return nil, err
+ }
+ serviceDetail.Statics.Instances =
&discovery.StInstance{
+ Count: instanceCount,
+ }
+ continue
+ }
+ instances, err := GetAllInstancesOfOneService(ctx,
serviceID)
+ if err != nil {
+ log.Error(fmt.Sprintf("get service[%s]'s all
instances failed", serviceID), err)
+ return nil, err
+ }
+ serviceDetail.Instances = instances
case "schemas":
schemas, err := GetSchemas(ctx,
GeneratorServiceFilter(ctx, mgs.ServiceInfo.ServiceId))
if err != nil {
@@ -1219,7 +1294,7 @@ func getServiceDetailUtil(ctx context.Context, mgs
*Service, countOnly bool, opt
}
serviceDetail.SchemaInfos = schemas
case "dependencies":
- //todo wait dependencied interface
+ //todo wait dependency interface
case "":
continue
default:
@@ -1259,7 +1334,11 @@ func UpdateRule(ctx context.Context, filter interface{},
m bson.M) error {
}
func UpdateSchema(ctx context.Context, filter interface{}, m bson.M, opts
...*options.FindOneAndUpdateOptions) error {
- return client.GetMongoClient().DocUpdate(ctx, CollectionSchema, filter,
m, opts...)
+ _, err := client.GetMongoClient().FindOneAndUpdate(ctx,
CollectionSchema, filter, m, opts...)
+ if err != nil {
+ return err
+ }
+ return nil
}
func DeleteSchema(ctx context.Context, filter interface{}) error {
@@ -1364,6 +1443,10 @@ func GetSchema(ctx context.Context, filter bson.M)
(*Schema, error) {
if err != nil {
return nil, err
}
+ if findRes.Err() != nil {
+ //not get any service,not db err
+ return nil, nil
+ }
var schema *Schema
err = findRes.Decode(&schema)
if err != nil {
@@ -1372,12 +1455,20 @@ func GetSchema(ctx context.Context, filter bson.M)
(*Schema, error) {
return schema, nil
}
-func SchemaExist(ctx context.Context, serviceID, schemaID string) (bool,
error) {
- num, err := client.GetMongoClient().Count(ctx, CollectionSchema,
GeneratorSchemaFilter(ctx, serviceID, schemaID))
+func SchemaSummaryExist(ctx context.Context, serviceID, schemaID string)
(bool, error) {
+ res, err := client.GetMongoClient().FindOne(ctx, CollectionSchema,
GeneratorSchemaFilter(ctx, serviceID, schemaID))
if err != nil {
return false, err
}
- return num != 0, nil
+ if res.Err() != nil {
+ return false, nil
+ }
+ var s Schema
+ err = res.Decode(&s)
+ if err != nil {
+ return false, err
+ }
+ return len(s.SchemaSummary) != 0, nil
}
// Instance management
@@ -1430,7 +1521,7 @@ func (ds *DataSource) RegisterInstance(ctx
context.Context, request *discovery.R
// GetInstances returns instances under the current domain
func (ds *DataSource) GetInstance(ctx context.Context, request
*discovery.GetOneInstanceRequest) (*discovery.GetOneInstanceResponse, error) {
- service := &Service{}
+ var service *Service
var err error
var serviceIDs []string
if len(request.ConsumerServiceId) > 0 {
@@ -2665,3 +2756,68 @@ func allowAcrossDimension(ctx context.Context,
providerService *Service, consume
}
return nil
}
+
+func GetInstanceCountOfOneService(ctx context.Context, serviceID string)
(int64, error) {
+ filter := GeneratorServiceInstanceFilter(ctx, serviceID)
+ count, err := client.GetMongoClient().Count(ctx, CollectionInstance,
filter)
+ if err != nil {
+ return 0, nil
+ }
+ return count, nil
+}
+
+func GetAllInstancesOfOneService(ctx context.Context, serviceID string)
([]*discovery.MicroServiceInstance, error) {
+ filter := GeneratorServiceInstanceFilter(ctx, serviceID)
+ res, err := client.GetMongoClient().Find(ctx, CollectionInstance,
filter)
+ if err != nil {
+ return nil, err
+ }
+ var instances []*discovery.MicroServiceInstance
+ for res.Next(ctx) {
+ var tmp Instance
+ err := res.Decode(&tmp)
+ if err != nil {
+ return nil, err
+ }
+ instances = append(instances, tmp.InstanceInfo)
+ }
+ return instances, nil
+}
+
+func GetInstances(ctx context.Context, filter bson.M) ([]*Instance, error) {
+ res, err := client.GetMongoClient().Find(ctx, CollectionInstance,
filter)
+ if err != nil {
+ return nil, err
+ }
+ var instances []*Instance
+ for res.Next(ctx) {
+ var tmp *Instance
+ err := res.Decode(&tmp)
+ if err != nil {
+ return nil, err
+ }
+ instances = append(instances, tmp)
+ }
+ return instances, nil
+}
+
+func GeneratorServiceVersionsFilter(ctx context.Context, service
*discovery.MicroServiceKey) bson.M {
+ domain := util.ParseDomain(ctx)
+ project := util.ParseProject(ctx)
+
+ return bson.M{
+ ColumnDomain: domain,
+ ColumnProject: project,
+ StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):
service.Environment,
+ StringBuilder([]string{ColumnServiceInfo, ColumnAppID}):
service.AppId,
+ StringBuilder([]string{ColumnServiceInfo, ColumnServiceName}):
service.ServiceName}
+}
+
+func GeneratorServiceInstanceFilter(ctx context.Context, serviceID string)
bson.M {
+ domain := util.ParseDomain(ctx)
+ project := util.ParseProject(ctx)
+ return bson.M{
+ ColumnDomain: domain,
+ ColumnProject: project,
+ StringBuilder([]string{ColumnInstanceInfo, ColumnServiceID}):
serviceID}
+}
diff --git a/datasource/mongo/ms_test.go b/datasource/mongo/ms_test.go
index 8ba907d..7fcf983 100644
--- a/datasource/mongo/ms_test.go
+++ b/datasource/mongo/ms_test.go
@@ -18,6 +18,7 @@
package mongo_test
import (
+ "fmt"
"strconv"
"strings"
"testing"
@@ -36,6 +37,7 @@ import (
"github.com/apache/servicecomb-service-center/server/config"
"github.com/apache/servicecomb-service-center/server/core"
"github.com/apache/servicecomb-service-center/server/plugin/quota"
+ "github.com/apache/servicecomb-service-center/server/service"
)
func init() {
@@ -45,19 +47,13 @@ func init() {
client.NewMongoClient(config)
}
-func TestServiceRegister(t *testing.T) {
- t.Run("Register service by mongo, should pass", func(t *testing.T) {
+func TestService_Register(t *testing.T) {
+ t.Run("Register service after init & install, should pass", func(t
*testing.T) {
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{
- ServiceId: "service-ms-appID_id",
AppId: "service-ms-appID",
ServiceName: "service-ms-serviceName",
Version: "32767.32767.32767.32767",
@@ -81,82 +77,195 @@ func TestServiceRegister(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
})
- t.Run("Register service with the same id by mongo, should pass", func(t
*testing.T) {
- request := &pb.CreateServiceRequest{
+
+ t.Run("register service with same key, should pass", func(t *testing.T)
{
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "service-ms-appID_id",
- AppId: "service-ms-appID11",
- ServiceName: "service-ms-serviceName11",
- Version: "32767.32767.32767.3276711",
- Alias: "service-ms-alias11",
+ ServiceName: "some-relay-ms-service-name",
+ Alias: "sr-ms-service-name",
+ AppId: "default",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ "xxxxxxxx",
+ },
+ Status: "UP",
},
- }
- resp, err :=
datasource.Instance().RegisterService(getContext(), request)
+ })
assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ErrServiceAlreadyExists,
resp.Response.GetCode())
- })
- t.Run("Register service with the same id by mongo, should pass", func(t
*testing.T) {
- request := &pb.CreateServiceRequest{
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ sameId := resp.ServiceId
+
+ // serviceName: some-relay-ms-service-name
+ // alias: sr1-ms-service-name
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "service-ms-appID_id_test",
- AppId: "service-ms-appID",
- ServiceName: "service-ms-serviceName",
- Version: "32767.32767.32767.32767",
- Alias: "service-ms-alias",
+ ServiceName: "some-relay-ms-service-name",
+ Alias: "sr1-ms-service-name",
+ AppId: "default",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ "xxxxxxxx",
+ },
+ Status: "UP",
},
- }
- resp, err :=
datasource.Instance().RegisterService(getContext(), request)
+ })
assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ErrServiceAlreadyExists,
resp.Response.GetCode())
- })
-}
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
-func TestGetService(t *testing.T) {
- t.Run("get a exist service by mongo, should pass", func(t *testing.T) {
- request := &pb.CreateServiceRequest{
+ // serviceName: some-relay1-ms-service-name
+ // alias: sr-ms-service-name
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "ms-service-query-id",
- ServiceName: "ms-service-query",
+ ServiceName: "some-relay1-ms-service-name",
+ Alias: "sr-ms-service-name",
AppId: "default",
- Version: "1.0.4",
- Level: "BACK",
- Properties: make(map[string]string),
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ "xxxxxxxx",
+ },
+ Status: "UP",
},
- }
-
- resp, err :=
datasource.Instance().RegisterService(getContext(), request)
+ })
+ assert.NotNil(t, resp)
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- request = &pb.CreateServiceRequest{
+ // serviceName: some-relay1-ms-service-name
+ // alias: sr-ms-service-name
+ // add serviceId field: sameId
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "ms-service-query-id1",
- ServiceName: "ms-service-query1",
+ ServiceId: sameId,
+ ServiceName: "some-relay1-ms-service-name",
+ Alias: "sr-ms-service-name",
AppId: "default",
- Version: "1.0.4",
- Level: "BACK",
- Properties: make(map[string]string),
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ "xxxxxxxx",
+ },
+ Status: "UP",
},
- }
+ })
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceAlreadyExists,
resp.Response.GetCode())
+
+ // serviceName: some-relay-ms-service-name
+ // alias: sr1-ms-service-name
+ // serviceId: sameId
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ ServiceId: sameId,
+ ServiceName: "some-relay-ms-service-name",
+ Alias: "sr1-ms-service-name",
+ AppId: "default",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ "xxxxxxxx",
+ },
+ Status: "UP",
+ },
+ })
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceAlreadyExists,
resp.Response.GetCode())
- resp, err = datasource.Instance().RegisterService(getContext(),
request)
+ // serviceName: some-relay-ms-service-name
+ // alias: sr1-ms-service-name
+ // serviceId: custom-id-ms-service-id -- different
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ ServiceId: "custom-id-ms-service-id",
+ ServiceName: "some-relay-ms-service-name",
+ Alias: "sr1-ms-service-name",
+ AppId: "default",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ "xxxxxxxx",
+ },
+ Status: "UP",
+ },
+ })
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, pb.ErrServiceAlreadyExists,
resp.Response.GetCode())
- // search service by serviceID
- queryResp, err :=
datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
- ServiceId: "ms-service-query-id",
+ // serviceName: some-relay1-ms-service-name
+ // alias: sr-ms-service-name
+ // serviceId: custom-id-ms-service-id -- different
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ ServiceId: "custom-id-ms-service-id",
+ ServiceName: "some-relay1-ms-service-name",
+ Alias: "sr-ms-service-name",
+ AppId: "default",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ "xxxxxxxx",
+ },
+ Status: "UP",
+ },
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
queryResp.Response.GetCode())
+ assert.Equal(t, pb.ErrServiceAlreadyExists,
resp.Response.GetCode())
})
- t.Run("get all service by mongo, should pass", func(t *testing.T) {
+
+ t.Run("same serviceId,different service, can not register again,error
is same as the service register twice",
+ func(t *testing.T) {
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ ServiceId:
"same-serviceId-service-ms",
+ ServiceName: "serviceA-service-ms",
+ AppId: "default-service-ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ "xxxxxxxx",
+ },
+ Status: "UP",
+ },
+ })
+
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, resp.Response.GetCode(),
pb.ResponseSuccess)
+
+ // same serviceId with different service name
+ resp, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ ServiceId:
"same-serviceId-service-ms",
+ ServiceName: "serviceB-service-ms",
+ AppId: "default-service-ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ "xxxxxxxx",
+ },
+ Status: "UP",
+ },
+ })
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceAlreadyExists,
resp.Response.GetCode())
+ })
+}
+
+func TestService_Get(t *testing.T) {
+ t.Run("get a exist service, should pass", func(t *testing.T) {
request := &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "ms-service-query-id3",
- ServiceName: "ms-service-query3",
+ ServiceId: "ms-service-query-id",
+ ServiceName: "ms-service-query",
AppId: "default",
Version: "1.0.4",
Level: "BACK",
@@ -166,223 +275,1430 @@ func TestGetService(t *testing.T) {
resp, err :=
datasource.Instance().RegisterService(getContext(), request)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, resp.Response.GetCode(), pb.ResponseSuccess)
// search service by serviceID
- queryResp, err :=
datasource.Instance().GetServices(getContext(), &pb.GetServicesRequest{})
+ queryResp, err :=
datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
+ ServiceId: "ms-service-query-id",
+ })
assert.NoError(t, err)
- assert.Greater(t, len(queryResp.Services), 0)
+ assert.Equal(t, queryResp.Response.GetCode(),
pb.ResponseSuccess)
})
- t.Run("get a exist service with id by mongo, should pass", func(t
*testing.T) {
- queryResp, err :=
datasource.Instance().ExistServiceByID(getContext(),
&pb.GetExistenceByIDRequest{
- ServiceId: "ms-service-query-id1",
- })
+ t.Run("query all services, should pass", func(t *testing.T) {
+ resp, err := datasource.Instance().GetServices(getContext(),
&pb.GetServicesRequest{})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
queryResp.Response.GetCode())
- assert.Equal(t, true, queryResp.Exist)
+ assert.Greater(t, len(resp.Services), 0)
})
+
t.Run("query a service by a not existed serviceId, should not pass",
func(t *testing.T) {
// not exist service
resp, err := datasource.Instance().GetService(getContext(),
&pb.GetServiceRequest{
ServiceId: "no-exist-service",
})
assert.NoError(t, err)
- assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+ assert.Equal(t, resp.Response.GetCode(), pb.ErrServiceNotExists)
})
-
}
-func TestUpdateService(t *testing.T) {
- t.Run("update service by mongo, should pass", func(t *testing.T) {
- request := &pb.CreateServiceRequest{
+func TestService_Update(t *testing.T) {
+ var serviceId string
+
+ t.Run("create service", func(t *testing.T) {
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "ms-service-update-new-id",
- ServiceName: "ms-service-update",
- AppId: "default",
- Version: "1.0.4",
- Level: "BACK",
- Properties: make(map[string]string),
+ Alias: "es_service_ms",
+ ServiceName: "update_prop_service_service_ms",
+ AppId: "update_prop_appId_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: "UP",
},
- }
-
- resp, err :=
datasource.Instance().RegisterService(getContext(), request)
+ })
assert.NoError(t, err)
- assert.Equal(t, resp.Response.GetCode(), pb.ResponseSuccess)
+ assert.NotNil(t, resp)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.NotEqual(t, "", resp.ServiceId)
+ serviceId = resp.ServiceId
+ })
- requestNew := &pb.UpdateServicePropsRequest{
- ServiceId: "ms-service-update-new-id",
+ t.Run("update properties while properties not nil", func(t *testing.T) {
+ request := &pb.UpdateServicePropsRequest{
+ ServiceId: serviceId,
+ Properties: make(map[string]string),
+ }
+ request2 := &pb.UpdateServicePropsRequest{
+ ServiceId: serviceId,
Properties: make(map[string]string),
}
- requestNew.Properties["k"] = "v"
- res, err := datasource.Instance().UpdateService(getContext(),
requestNew)
+ request.Properties["test"] = "1"
+ request2.Properties["k"] = "v"
+ resp, err := datasource.Instance().UpdateService(getContext(),
request)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().UpdateService(getContext(),
request2)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, res.Response.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- respGetService, err :=
datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{ServiceId:
"ms-service-update-new-id"})
+ respGetService, err :=
datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
+ ServiceId: serviceId,
+ })
assert.NoError(t, err)
+ assert.Equal(t, serviceId, respGetService.Service.ServiceId)
+ assert.Equal(t, "", respGetService.Service.Properties["test"])
assert.Equal(t, "v", respGetService.Service.Properties["k"])
})
-}
-func TestTagsAdd(t *testing.T) {
- // create service
- t.Run("create service, the request is valid, should pass", func(t
*testing.T) {
- svc1 := &pb.MicroService{
- ServiceId: "service_tag_id",
- AppId: "create_tag_group_ms",
- ServiceName: "create_tag_service_ms",
- Version: "1.0.0",
- Level: "FRONT",
- Status: pb.MS_UP,
+ t.Run("update service that does not exist", func(t *testing.T) {
+ r := &pb.UpdateServicePropsRequest{
+ ServiceId: "not_exist_service_service_ms",
+ Properties: make(map[string]string),
}
- resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
- Service: svc1,
- })
+ resp, err := datasource.Instance().UpdateService(getContext(),
r)
assert.NoError(t, err)
- assert.NotEqual(t, "", resp.ServiceId)
+ assert.NotEqual(t, pb.ResponseSuccess, resp.Response.GetCode())
})
- //
- t.Run("create service, the request is valid, should pass", func(t
*testing.T) {
- defaultQuota := quota.DefaultTagQuota
- tags := make(map[string]string, defaultQuota)
- for i := 0; i < defaultQuota; i++ {
- s := "tag" + strconv.Itoa(i)
- tags[s] = s
+ t.Run("update service by removing the properties", func(t *testing.T) {
+ r := &pb.UpdateServicePropsRequest{
+ ServiceId: serviceId,
+ Properties: nil,
}
- resp, err := datasource.Instance().AddTags(getContext(),
&pb.AddServiceTagsRequest{
- ServiceId: "service_tag_id",
- Tags: tags,
- })
+ resp, err := datasource.Instance().UpdateService(getContext(),
r)
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- })
+ r = &pb.UpdateServicePropsRequest{
+ ServiceId: "",
+ Properties: map[string]string{},
+ }
+ resp, err = datasource.Instance().UpdateService(getContext(), r)
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
}
-func TestTagsGet(t *testing.T) {
- t.Run("create service and add tags, the request is valid, should pass",
func(t *testing.T) {
- svc := &pb.MicroService{
- ServiceId: "get_tag_group_ms_id",
- AppId: "get_tag_group_ms",
- ServiceName: "get_tag_service_ms",
- Version: "1.0.0",
- Level: "FRONT",
- Status: pb.MS_UP,
- }
+func TestService_Detail(t *testing.T) {
+ var (
+ serviceId string
+ )
+
+ t.Run("execute 'get detail' operation", func(t *testing.T) {
+ log.Info("should be passed")
resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
- Service: svc,
+ Service: &pb.MicroService{
+ AppId: "govern_service_group",
+ ServiceName: "govern_service_name",
+ Version: "3.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ serviceId = resp.ServiceId
- respAddTags, err := datasource.Instance().AddTags(getContext(),
&pb.AddServiceTagsRequest{
- ServiceId: "get_tag_group_ms_id",
- Tags: map[string]string{
- "a": "test",
- "b": "b",
- },
+ datasource.Instance().ModifySchema(getContext(),
&pb.ModifySchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "schemaId",
+ Schema: "detail",
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respAddTags.Response.GetCode())
- })
- t.Run("the request is valid", func(t *testing.T) {
- resp, err := datasource.Instance().GetTags(getContext(),
&pb.GetServiceTagsRequest{
- ServiceId: "get_tag_group_ms_id",
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ datasource.Instance().RegisterInstance(getContext(),
&pb.RegisterInstanceRequest{
+ Instance: &pb.MicroServiceInstance{
+ ServiceId: serviceId,
+ Endpoints: []string{
+ "govern:127.0.0.1:8080",
+ },
+ HostName: "UT-HOST",
+ Status: pb.MSI_UP,
+ },
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- assert.Equal(t, "test", resp.Tags["a"])
+
+ log.Info("when get invalid service detail, should be failed")
+ respD, err :=
datasource.Instance().GetServiceDetail(getContext(), &pb.GetServiceRequest{
+ ServiceId: "",
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess, respD.Response.GetCode())
+ //
+ log.Info("when get a service detail, should be passed")
+ respGetServiceDetail, err :=
datasource.Instance().GetServiceDetail(getContext(), &pb.GetServiceRequest{
+ ServiceId: serviceId,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respGetServiceDetail.Response.GetCode())
+ //
+ respDelete, err :=
datasource.Instance().UnregisterService(getContext(), &pb.DeleteServiceRequest{
+ ServiceId: serviceId,
+ Force: true,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respDelete.Response.GetCode())
+ //
+ respGetServiceDetail, err =
datasource.Instance().GetServiceDetail(getContext(), &pb.GetServiceRequest{
+ ServiceId: serviceId,
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess,
respGetServiceDetail.Response.GetCode())
})
}
-func TestTagUpdate(t *testing.T) {
- t.Run("add service and add tags, the request is valid, should pass",
func(t *testing.T) {
- svc := &pb.MicroService{
- ServiceId: "update_tag_group_ms_id",
- AppId: "update_tag_group_ms",
- ServiceName: "update_tag_service_ms",
- Version: "1.0.0",
- Level: "FRONT",
- Status: pb.MS_UP,
- }
- resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
- Service: svc,
+func TestService_Info(t *testing.T) {
+ t.Run("get all services", func(t *testing.T) {
+ log.Info("should be passed")
+ resp, err :=
datasource.Instance().GetServicesInfo(getContext(), &pb.GetServicesInfoRequest{
+ Options: []string{"all"},
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- respAddTags, err := datasource.Instance().AddTags(getContext(),
&pb.AddServiceTagsRequest{
- ServiceId: "update_tag_group_ms_id",
- Tags: map[string]string{
- "a": "test",
- "b": "b",
- },
+ resp, err = datasource.Instance().GetServicesInfo(getContext(),
&pb.GetServicesInfoRequest{
+ Options: []string{""},
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respAddTags.Response.GetCode())
- })
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- t.Run("the request is valid, should pass", func(t *testing.T) {
- resp, err := datasource.Instance().UpdateTag(getContext(),
&pb.UpdateServiceTagRequest{
- ServiceId: "update_tag_group_ms_id",
- Key: "a",
- Value: "update",
+ resp, err = datasource.Instance().GetServicesInfo(getContext(),
&pb.GetServicesInfoRequest{
+ Options: []string{"tags", "rules", "instances",
"schemas", "statistics"},
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().GetServicesInfo(getContext(),
&pb.GetServicesInfoRequest{
+ Options: []string{"statistics"},
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().GetServicesInfo(getContext(),
&pb.GetServicesInfoRequest{
+ Options: []string{"instances"},
+ CountOnly: true,
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
})
}
-func TestTagsDelete(t *testing.T) {
- t.Run("create service and add tags, the request is valid, should pass",
func(t *testing.T) {
- resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+func TestService_Delete(t *testing.T) {
+ var (
+ serviceContainInstId string
+ serviceNoInstId string
+ )
+
+ t.Run("create service & instance", func(t *testing.T) {
+ respCreate, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "delete_tag_group_ms_id",
- AppId: "delete_tag_group_ms",
- ServiceName: "delete_tag_service_ms",
+ ServiceName: "delete_service_with_inst_ms",
+ AppId: "delete_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: "UP",
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreate.Response.GetCode())
+ serviceContainInstId = respCreate.ServiceId
+
+ log.Info("attach instance")
+ instance := &pb.MicroServiceInstance{
+ ServiceId: serviceContainInstId,
+ Endpoints: []string{
+ "deleteService:127.0.0.1:8080",
+ },
+ HostName: "delete-host-ms",
+ Status: pb.MSI_UP,
+ }
+ respCreateIns, err :=
datasource.Instance().RegisterInstance(getContext(),
&pb.RegisterInstanceRequest{
+ Instance: instance,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateIns.Response.GetCode())
+
+ log.Info("create service without instance")
+ provider := &pb.MicroService{
+ ServiceName: "delete_service_no_inst_ms",
+ AppId: "delete_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: "UP",
+ }
+ respCreate, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: provider,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreate.Response.GetCode())
+ serviceNoInstId = respCreate.ServiceId
+
+ respCreate, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ ServiceName: "delete_service_consumer_ms",
+ AppId: "delete_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: "UP",
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreate.Response.GetCode())
+ })
+
+ t.Run("delete a service which contains instances with no force flag",
func(t *testing.T) {
+ log.Info("should not pass")
+ resp, err :=
datasource.Instance().UnregisterService(getContext(), &pb.DeleteServiceRequest{
+ ServiceId: serviceContainInstId,
+ Force: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+
+ t.Run("delete a service which contains instances with force flag",
func(t *testing.T) {
+ log.Info("should pass")
+ resp, err :=
datasource.Instance().UnregisterService(getContext(), &pb.DeleteServiceRequest{
+ ServiceId: serviceContainInstId,
+ Force: true,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+
+ // todo: add delete service depended by consumer after finishing
dependency management
+
+ t.Run("delete a service which depended by consumer with force flag",
func(t *testing.T) {
+ log.Info("should pass")
+ resp, err :=
datasource.Instance().UnregisterService(getContext(), &pb.DeleteServiceRequest{
+ ServiceId: serviceNoInstId,
+ Force: true,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+
+ t.Run("delete a service with no force flag", func(t *testing.T) {
+ log.Info("should not pass")
+ resp, err :=
datasource.Instance().UnregisterService(getContext(), &pb.DeleteServiceRequest{
+ ServiceId: serviceNoInstId,
+ Force: false,
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+}
+
+func TestApplication_Get(t *testing.T) {
+ t.Run("execute 'get apps' operation", func(t *testing.T) {
+ log.Info("when request is valid, should be passed")
+ resp, err :=
datasource.Instance().GetApplications(getContext(), &pb.GetAppsRequest{})
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().GetApplications(getContext(),
&pb.GetAppsRequest{
+ Environment: pb.ENV_ACCEPT,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+}
+
+func TestTags_Add(t *testing.T) {
+ var (
+ serviceId1 string
+ serviceId2 string
+ )
+
+ // create service
+ t.Run("create service", func(t *testing.T) {
+ svc1 := &pb.MicroService{
+ AppId: "create_tag_group_ms",
+ ServiceName: "create_tag_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ }
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: svc1,
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, "", resp.ServiceId)
+ serviceId1 = resp.ServiceId
+
+ svc2 := &pb.MicroService{
+ AppId: "create_tag_group_ms",
+ ServiceName: "create_tag_service_ms",
+ Version: "1.0.1",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ }
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
+ Service: svc2,
+ })
+ assert.NoError(t, err)
+ assert.NotNil(t, "", resp.ServiceId)
+ serviceId2 = resp.ServiceId
+ })
+
+ t.Run("the request is invalid", func(t *testing.T) {
+ resp, err := datasource.Instance().AddTags(getContext(),
&pb.AddServiceTagsRequest{
+ ServiceId: "noServiceTest",
+ Tags: map[string]string{
+ "a": "test",
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+ })
+
+ t.Run("the request is valid", func(t *testing.T) {
+ defaultQuota := quota.DefaultTagQuota
+ tags := make(map[string]string, defaultQuota)
+ for i := 0; i < defaultQuota; i++ {
+ s := "tag" + strconv.Itoa(i)
+ tags[s] = s
+ }
+ resp, err := datasource.Instance().AddTags(getContext(),
&pb.AddServiceTagsRequest{
+ ServiceId: serviceId1,
+ Tags: tags,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+
+ t.Run("tag's quota exceeded", func(t *testing.T) {
+ size := quota.DefaultTagQuota / 2
+ tags := make(map[string]string, size)
+ for i := 0; i < size; i++ {
+ s := "tag" + strconv.Itoa(i)
+ tags[s] = s
+ }
+ resp, err := datasource.Instance().AddTags(getContext(),
&pb.AddServiceTagsRequest{
+ ServiceId: serviceId2,
+ Tags: tags,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ tags["out"] = "range"
+ resp, _ = datasource.Instance().AddTags(getContext(),
&pb.AddServiceTagsRequest{
+ ServiceId: serviceId2,
+ Tags: tags,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrNotEnoughQuota, resp.Response.GetCode())
+ })
+}
+
+func TestTags_Get(t *testing.T) {
+ var serviceId string
+ t.Run("create service and add tags", func(t *testing.T) {
+ svc := &pb.MicroService{
+ AppId: "get_tag_group_ms",
+ ServiceName: "get_tag_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ }
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: svc,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ serviceId = resp.ServiceId
+
+ respAddTags, err := datasource.Instance().AddTags(getContext(),
&pb.AddServiceTagsRequest{
+ ServiceId: serviceId,
+ Tags: map[string]string{
+ "a": "test",
+ "b": "b",
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respAddTags.Response.GetCode())
+ })
+
+ t.Run("the request is invalid", func(t *testing.T) {
+ resp, err := datasource.Instance().GetTags(getContext(),
&pb.GetServiceTagsRequest{
+ ServiceId: "noThisService",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().GetTags(getContext(),
&pb.GetServiceTagsRequest{
+ ServiceId: "",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().GetTags(getContext(),
&pb.GetServiceTagsRequest{
+ ServiceId: strings.Repeat("x", 65),
+ })
+ assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+ })
+
+ t.Run("the request is valid", func(t *testing.T) {
+ resp, err := datasource.Instance().GetTags(getContext(),
&pb.GetServiceTagsRequest{
+ ServiceId: serviceId,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, "test", resp.Tags["a"])
+ })
+}
+
+func TestTag_Update(t *testing.T) {
+ var serviceId string
+ t.Run("add service and add tags", func(t *testing.T) {
+ svc := &pb.MicroService{
+ AppId: "update_tag_group_ms",
+ ServiceName: "update_tag_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ }
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: svc,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ serviceId = resp.ServiceId
+
+ respAddTags, err := datasource.Instance().AddTags(getContext(),
&pb.AddServiceTagsRequest{
+ ServiceId: serviceId,
+ Tags: map[string]string{
+ "a": "test",
+ "b": "b",
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respAddTags.Response.GetCode())
+ })
+
+ t.Run("the request is invalid", func(t *testing.T) {
+
+ resp, err := datasource.Instance().UpdateTag(getContext(),
&pb.UpdateServiceTagRequest{
+ ServiceId: "noneservice",
+ Key: "a",
+ Value: "update",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().UpdateTag(getContext(),
&pb.UpdateServiceTagRequest{
+ ServiceId: serviceId,
+ Key: "notexisttag",
+ Value: "update",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrTagNotExists, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().UpdateTag(getContext(),
&pb.UpdateServiceTagRequest{
+ ServiceId: serviceId,
+ Key: strings.Repeat("x", 65),
+ Value: "v",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrTagNotExists, resp.Response.GetCode())
+ })
+
+ t.Run("the request is valid", func(t *testing.T) {
+ resp, err := datasource.Instance().UpdateTag(getContext(),
&pb.UpdateServiceTagRequest{
+ ServiceId: serviceId,
+ Key: "a",
+ Value: "update",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+}
+
+func TestTags_Delete(t *testing.T) {
+ var serviceId string
+ t.Run("create service and add tags", func(t *testing.T) {
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "delete_tag_group_ms",
+ ServiceName: "delete_tag_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ serviceId = resp.ServiceId
+
+ respAddTages, err :=
datasource.Instance().AddTags(getContext(), &pb.AddServiceTagsRequest{
+ ServiceId: serviceId,
+ Tags: map[string]string{
+ "a": "test",
+ "b": "b",
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respAddTages.Response.GetCode())
+ })
+
+ t.Run("the request is invalid", func(t *testing.T) {
+ resp, err := datasource.Instance().DeleteTags(getContext(),
&pb.DeleteServiceTagsRequest{
+ ServiceId: "noneservice",
+ Keys: []string{"a", "b"},
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().DeleteTags(getContext(),
&pb.DeleteServiceTagsRequest{
+ ServiceId: serviceId,
+ Keys: []string{"c"},
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrTagNotExists, resp.Response.GetCode())
+ })
+
+ t.Run("the request is valid", func(t *testing.T) {
+ resp, err := datasource.Instance().DeleteTags(getContext(),
&pb.DeleteServiceTagsRequest{
+ ServiceId: serviceId,
+ Keys: []string{"a", "b"},
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ respGetTags, err := datasource.Instance().GetTags(getContext(),
&pb.GetServiceTagsRequest{
+ ServiceId: serviceId,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, "", respGetTags.Tags["a"])
+ })
+}
+
+func TestRule_Add(t *testing.T) {
+ var (
+ serviceId1 string
+ serviceId2 string
+ )
+
+ t.Run("register service and instance", func(t *testing.T) {
+ respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_rule_group_ms",
+ ServiceName: "create_rule_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceId1 = respCreateService.ServiceId
+
+ respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_rule_group_ms",
+ ServiceName: "create_rule_service_ms",
+ Version: "1.0.1",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceId2 = respCreateService.ServiceId
+ })
+
+ t.Run("invalid request", func(t *testing.T) {
+ respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
+ ServiceId: "not_exist_service_ms",
+ Rules: []*pb.AddOrUpdateServiceRule{
+ {
+ RuleType: "BLACK",
+ Attribute: "ServiceName",
+ Pattern: "Test*",
+ Description: "test white",
+ },
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess, respAddRule)
+ })
+
+ t.Run("request is valid", func(t *testing.T) {
+ respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
+ ServiceId: serviceId1,
+ Rules: []*pb.AddOrUpdateServiceRule{
+ {
+ RuleType: "BLACK",
+ Attribute: "ServiceName",
+ Pattern: "Test*",
+ Description: "test black",
+ },
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
+ ruleId := respAddRule.RuleIds[0]
+ assert.NotEqual(t, "", ruleId)
+
+ respAddRule, err = datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
+ ServiceId: serviceId1,
+ Rules: []*pb.AddOrUpdateServiceRule{
+ {
+ RuleType: "BLACK",
+ Attribute: "ServiceName",
+ Pattern: "Test*",
+ Description: "test change black",
+ },
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
+ assert.Equal(t, 0, len(respAddRule.RuleIds))
+
+ respAddRule, err = datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
+ ServiceId: serviceId1,
+ Rules: []*pb.AddOrUpdateServiceRule{
+ {
+ RuleType: "WHITE",
+ Attribute: "ServiceName",
+ Pattern: "Test*",
+ Description: "test white",
+ },
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
+ })
+
+ t.Run("create rule out of quota", func(t *testing.T) {
+ size := quota.DefaultRuleQuota + 1
+ rules := make([]*pb.AddOrUpdateServiceRule, 0, size)
+ for i := 0; i < size; i++ {
+ rules = append(rules, &pb.AddOrUpdateServiceRule{
+ RuleType: "BLACK",
+ Attribute: "ServiceName",
+ Pattern: strconv.Itoa(i),
+ Description: "test white",
+ })
+ }
+
+ resp, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
+ ServiceId: serviceId2,
+ Rules: rules[:size-1],
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
+ ServiceId: serviceId2,
+ Rules: rules[size-1:],
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrNotEnoughQuota, resp.Response.GetCode())
+ })
+}
+
+func TestRule_Get(t *testing.T) {
+ var (
+ serviceId string
+ ruleId string
+ )
+
+ t.Run("register service and rules", func(t *testing.T) {
+ respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "get_rule_group_ms",
+ ServiceName: "get_rule_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceId = respCreateService.ServiceId
+
+ respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
+ ServiceId: serviceId,
+ Rules: []*pb.AddOrUpdateServiceRule{
+ {
+ RuleType: "BLACK",
+ Attribute: "ServiceName",
+ Pattern: "Test*",
+ Description: "test BLACK",
+ },
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
+ ruleId = respAddRule.RuleIds[0]
+ assert.NotEqual(t, "", ruleId)
+ })
+
+ t.Run("get when request is invalid", func(t *testing.T) {
+ respGetRule, err :=
datasource.Instance().GetRules(getContext(), &pb.GetServiceRulesRequest{
+ ServiceId: "not_exist_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists,
respGetRule.Response.GetCode())
+ })
+
+ t.Run("get when request is valid", func(t *testing.T) {
+ respGetRule, err :=
datasource.Instance().GetRules(getContext(), &pb.GetServiceRulesRequest{
+ ServiceId: serviceId,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respGetRule.Response.GetCode())
+ assert.Equal(t, ruleId, respGetRule.Rules[0].RuleId)
+ })
+}
+
+func TestRule_Delete(t *testing.T) {
+ var (
+ serviceId string
+ ruleId string
+ )
+ t.Run("register service and rules", func(t *testing.T) {
+ respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "delete_rule_group_ms",
+ ServiceName: "delete_rule_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceId = respCreateService.ServiceId
+
+ respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
+ ServiceId: serviceId,
+ Rules: []*pb.AddOrUpdateServiceRule{
+ {
+ RuleType: "BLACK",
+ Attribute: "ServiceName",
+ Pattern: "Test*",
+ Description: "test BLACK",
+ },
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
+ ruleId = respAddRule.RuleIds[0]
+ assert.NotEqual(t, "", ruleId)
+ })
+
+ t.Run("delete when request is invalid", func(t *testing.T) {
+ resp, err := datasource.Instance().DeleteRule(getContext(),
&pb.DeleteServiceRulesRequest{
+ ServiceId: "not_exist_service_ms",
+ RuleIds: []string{"1000000"},
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().DeleteRule(getContext(),
&pb.DeleteServiceRulesRequest{
+ ServiceId: serviceId,
+ RuleIds: []string{"not_exist_rule"},
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrRuleNotExists, resp.Response.GetCode())
+ })
+
+ t.Run("delete when request is valid", func(t *testing.T) {
+ resp, err := datasource.Instance().DeleteRule(getContext(),
&pb.DeleteServiceRulesRequest{
+ ServiceId: serviceId,
+ RuleIds: []string{ruleId},
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ respGetRule, err :=
datasource.Instance().GetRules(getContext(), &pb.GetServiceRulesRequest{
+ ServiceId: serviceId,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, 0, len(respGetRule.Rules))
+ })
+}
+
+func TestRule_Update(t *testing.T) {
+ var (
+ serviceId string
+ ruleId string
+ )
+
+ t.Run("create service and rules", func(t *testing.T) {
+ respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "update_rule_group_ms",
+ ServiceName: "update_rule_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceId = respCreateService.ServiceId
+
+ respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
+ ServiceId: serviceId,
+ Rules: []*pb.AddOrUpdateServiceRule{
+ {
+ RuleType: "BLACK",
+ Attribute: "ServiceName",
+ Pattern: "Test*",
+ Description: "test BLACK",
+ },
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
+ ruleId = respAddRule.RuleIds[0]
+ assert.NotEqual(t, "", ruleId)
+ })
+
+ t.Run("update when request is invalid", func(t *testing.T) {
+ rule := &pb.AddOrUpdateServiceRule{
+ RuleType: "BLACK",
+ Attribute: "ServiceName",
+ Pattern: "Test*",
+ Description: "test BLACK update",
+ }
+ resp, err := datasource.Instance().UpdateRule(getContext(),
&pb.UpdateServiceRuleRequest{
+ ServiceId: "not_exist_service_ms",
+ RuleId: ruleId,
+ Rule: rule,
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().UpdateRule(getContext(),
&pb.UpdateServiceRuleRequest{
+ ServiceId: serviceId,
+ RuleId: "not_exist_rule_ms",
+ Rule: rule,
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().UpdateRule(getContext(),
&pb.UpdateServiceRuleRequest{
+ ServiceId: serviceId,
+ RuleId: ruleId,
+ Rule: &pb.AddOrUpdateServiceRule{
+ RuleType: "WHITE",
+ Attribute: "ServiceName",
+ Pattern: "Test*",
+ Description: "test white update",
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+
+ t.Run("update when request is valid", func(t *testing.T) {
+ resp, err := datasource.Instance().UpdateRule(getContext(),
&pb.UpdateServiceRuleRequest{
+ ServiceId: serviceId,
+ RuleId: ruleId,
+ Rule: &pb.AddOrUpdateServiceRule{
+ RuleType: "BLACK",
+ Attribute: "AppId",
+ Pattern: "Test*",
+ Description: "test white update",
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+}
+
+func TestSchema_Create(t *testing.T) {
+ var (
+ serviceIdDev string
+ )
+
+ t.Run("create service, should pass", func(t *testing.T) {
+ svc := &pb.MicroService{
+ Alias: "create_schema_group_service_ms",
+ ServiceName: "create_schema_service_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ Environment: pb.ENV_DEV,
+ }
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: svc,
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, "", resp.ServiceId)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ serviceIdDev = resp.ServiceId
+
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schema_group_service_ms",
+ ServiceName: "create_schema_service_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ Environment: pb.ENV_PROD,
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, "", resp.ServiceId)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+
+ t.Run("create schemas out of gauge", func(t *testing.T) {
+ size := quota.DefaultSchemaQuota + 1
+ schemaIds := make([]string, 0, size)
+ schemas := make([]*pb.Schema, 0, size)
+ for i := 0; i < size; i++ {
+ s := "ServiceCombTestTheLimitOfSchemasServiceMS" +
strconv.Itoa(i)
+
+ schemaIds = append(schemaIds, s)
+ schemas = append(schemas, &pb.Schema{
+ SchemaId: s,
+ Schema: s,
+ Summary: s,
+ })
+ }
+
+ resp, err := datasource.Instance().ModifySchemas(getContext(),
&pb.ModifySchemasRequest{
+ ServiceId: serviceIdDev,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrNotEnoughQuota, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().ModifySchemas(getContext(),
&pb.ModifySchemasRequest{
+ ServiceId: serviceIdDev,
+ Schemas: schemas[:quota.DefaultSchemaQuota],
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ //resp, err = datasource.Instance().ModifySchemas(getContext(),
&pb.ModifySchemasRequest{
+ // ServiceId: serviceIdDev,
+ // Schemas: schemas,
+ //})
+ //assert.NoError(t, err)
+ //assert.Equal(t, pb.ErrNotEnoughQuota, resp.Response.GetCode())
+ })
+
+ //
+ t.Run("batch create schemas in dev env", func(t *testing.T) {
+ var (
+ serviceIdDev1 string
+ serviceIdDev2 string
+ )
+
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schemas_dev_service_ms",
+ ServiceName:
"create_schemas_service_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ Environment: pb.ENV_DEV,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ serviceIdDev1 = resp.ServiceId
+
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schemas_dev_service_ms",
+ ServiceName:
"create_schemas_service_service_ms",
+ Version: "1.0.1",
+ Level: "FRONT",
+ Schemas: []string{
+ "first_schemaId_service_ms",
+ },
+ Status: pb.MS_UP,
+ Environment: pb.ENV_DEV,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ serviceIdDev2 = resp.ServiceId
+
+ schemas := []*pb.Schema{
+ {
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ Summary: "first0summary_service_ms",
+ },
+ {
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ Summary: "first0summary_service_ms",
+ },
+ }
+ respCreateSchema, err :=
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdDev1,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateSchema.Response.GetCode())
+ //
+ schemas = []*pb.Schema{
+ {
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_change_service_ms",
+ Summary: "first0summary1change_service_ms",
+ },
+ }
+ respCreateSchema, err =
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdDev1,
+ Schemas: schemas,
+ })
+
+ schemas = []*pb.Schema{
+ {
+ SchemaId: "second_schemaId_service_ms",
+ Schema: "second_schema_service_ms",
+ Summary: "second0summary_service_ms",
+ },
+ }
+ respCreateSchema, err =
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdDev1,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateSchema.Response.GetCode())
+
+ respGetService, err :=
datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
+ ServiceId: serviceIdDev1,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respGetService.Response.GetCode())
+ assert.Equal(t, []string{"second_schemaId_service_ms"},
respGetService.Service.Schemas)
+
+ schemas = []*pb.Schema{
+ {
+ SchemaId: "second_schemaId_service_ms",
+ Schema: "second_schema_service_ms",
+ Summary: "second0summary_service_ms",
+ },
+ }
+ respCreateSchema, err =
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdDev2,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateSchema.Response.GetCode())
+
+ respGetService, err =
datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
+ ServiceId: serviceIdDev2,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respGetService.Response.GetCode())
+ assert.Equal(t, []string{"second_schemaId_service_ms"},
respGetService.Service.Schemas)
+ })
+ //
+ t.Run("batch create schemas in production env", func(t *testing.T) {
+ var (
+ serviceIdPro1 string
+ serviceIdPro2 string
+ )
+
+ respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schemas_prod_service_ms",
+ ServiceName:
"create_schemas_service_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ Environment: pb.ENV_PROD,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceIdPro1 = respCreateService.ServiceId
+
+ respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schemas_prod_service_ms",
+ ServiceName:
"create_schemas_service_service_ms",
+ Version: "1.0.1",
+ Level: "FRONT",
+ Schemas: []string{
+ "first_schemaId_service_ms",
+ "second_schemaId_service_ms",
+ },
+ Status: pb.MS_UP,
+ Environment: pb.ENV_PROD,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceIdPro2 = respCreateService.ServiceId
+
+ schemas := []*pb.Schema{
+ {
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ Summary: "first0summary_service_ms",
+ },
+ {
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ Summary: "first0summary_service_ms",
+ },
+ }
+ respModifySchemas, err :=
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdPro1,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchemas.Response.GetCode())
+
+ respGetService, err :=
datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
+ ServiceId: serviceIdPro1,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respGetService.Response.GetCode())
+ assert.Equal(t, []string{"first_schemaId_service_ms"},
respGetService.Service.Schemas)
+
+ respModifySchemas, err =
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdPro1,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchemas.Response.GetCode())
+
+ schemas = []*pb.Schema{
+ {
+ SchemaId: "second_schemaId_service_ms",
+ Schema: "second_schema_service_ms",
+ Summary: "second0summary_service_ms",
+ },
+ }
+ respModifySchemas, err =
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdPro1,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrUndefinedSchemaID,
respModifySchemas.Response.GetCode())
+ fmt.Println(serviceIdPro2)
+
+ respModifySchema, err :=
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro2,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ schemas = []*pb.Schema{
+ {
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ Summary: "first0summary_service_ms",
+ },
+ }
+ respModifySchemas, err =
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdPro2,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchemas.Response.GetCode())
+ //
+ respExist, err :=
datasource.Instance().ExistSchema(getContext(), &pb.GetExistenceRequest{
+ Type: service.ExistTypeSchema,
+ ServiceId: serviceIdPro2,
+ SchemaId: "first_schemaId_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, "first0summary_service_ms", respExist.Summary)
+ //
+ respModifySchemas, err =
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdPro2,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchemas.Response.GetCode())
+ })
+
+ //
+ t.Run("create a schema in dev env", func(t *testing.T) {
+ var (
+ serviceIdDev1 string
+ serviceIdDev2 string
+ )
+
+ respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schema_dev_service_ms",
+ ServiceName: "create_schema_service_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ Environment: pb.ENV_DEV,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceIdDev1 = respCreateService.ServiceId
+
+ respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schema_dev_service_ms",
+ ServiceName: "create_schema_service_service_ms",
+ Version: "1.0.1",
+ Level: "FRONT",
+ Schemas: []string{
+ "first_schemaId_service_ms",
+ },
+ Status: pb.MS_UP,
+ Environment: pb.ENV_DEV,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceIdDev2 = respCreateService.ServiceId
+
+ respModifySchema, err :=
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdDev1,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdDev2,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdDev1,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_change_service_ms",
+ Summary: "first0summary1change_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdDev1,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ Summary: "first0summary_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdDev1,
+ SchemaId: "second_schemaId_service_ms",
+ Schema: "second_schema_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ })
+ //
+ t.Run("create a schema in production env", func(t *testing.T) {
+ var (
+ serviceIdPro1 string
+ serviceIdPro2 string
+ )
+
+ respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schema_prod_service_ms",
+ ServiceName: "create_schema_service_service_ms",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
+ Environment: pb.ENV_PROD,
},
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceIdPro1 = respCreateService.ServiceId
- respAddTages, err :=
datasource.Instance().AddTags(getContext(), &pb.AddServiceTagsRequest{
- ServiceId: "delete_tag_group_ms_id",
- Tags: map[string]string{
- "a": "test",
- "b": "b",
+ respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schema_prod_service_ms",
+ ServiceName: "create_schema_service_service_ms",
+ Version: "1.0.1",
+ Level: "FRONT",
+ Schemas: []string{
+ "first_schemaId_service_ms",
+ "second_schemaId_service_ms",
+ },
+ Status: pb.MS_UP,
+ Environment: pb.ENV_PROD,
},
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respAddTages.Response.GetCode())
- })
- t.Run("the request is valid, should pass", func(t *testing.T) {
- resp, err := datasource.Instance().DeleteTags(getContext(),
&pb.DeleteServiceTagsRequest{
- ServiceId: "delete_tag_group_ms_id",
- Keys: []string{"b"},
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceIdPro2 = respCreateService.ServiceId
+
+ respModifySchema, err :=
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_change_service_ms",
+ Summary: "first0summary1change_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ Summary: "first0summary_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: "second_schemaId_service_ms",
+ Schema: "second_schema_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
- respTags, err := datasource.Instance().GetTags(getContext(),
&pb.GetServiceTagsRequest{
- ServiceId: "delete_tag_group_ms_id",
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro2,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, respTags.Response.GetCode())
- assert.Equal(t, "", respTags.Tags["b"])
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
})
-}
+ //
+ t.Run("create a schema in empty env", func(t *testing.T) {
+ var (
+ serviceIdPro1 string
+ serviceIdPro2 string
+ )
-func TestRuleAdd(t *testing.T) {
- t.Run("register service, the request is valid, should pass", func(t
*testing.T) {
+ log.Info("register service")
respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "create_rule_group_ms_id",
- AppId: "create_rule_group_ms",
- ServiceName: "create_rule_service_ms",
+ AppId: "create_schema_empty_service_ms",
+ ServiceName: "create_schema_service_service_ms",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
@@ -390,91 +1706,289 @@ func TestRuleAdd(t *testing.T) {
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
- })
- t.Run("register service, the request is valid, should pass", func(t
*testing.T) {
- respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
- ServiceId: "create_rule_group_ms_id",
- Rules: []*pb.AddOrUpdateServiceRule{
- {
- RuleType: "BLACK",
- Attribute: "ServiceName",
- Pattern: "Test*",
- Description: "test black",
+ serviceIdPro1 = respCreateService.ServiceId
+
+ respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "create_schema_empty_service_ms",
+ ServiceName: "create_schema_service_service_ms",
+ Version: "1.0.1",
+ Level: "FRONT",
+ Schemas: []string{
+ "first_schemaId_service_ms",
+ "second_schemaId_service_ms",
},
+ Status: pb.MS_UP,
},
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
- ruleId := respAddRule.RuleIds[0]
- assert.NotEqual(t, "", ruleId)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceIdPro2 = respCreateService.ServiceId
+
+ log.Info("create a schema for service whose schemaID is empty")
+ respModifySchema, err :=
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ log.Info("modify schema for the service whose schema summary is
empty")
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_change_service_ms",
+ Summary: "first0summary1change_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ log.Info("modify schema for the service whose schema summary
already exist")
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ Summary: "first0summary_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ log.Info("add schema")
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: "second_schemaId_service_ms",
+ Schema: "second_schema_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
+
+ log.Info("modify schema for the service whose schemaId already
exist")
+ respModifySchema, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro2,
+ SchemaId: "first_schemaId_service_ms",
+ Schema: "first_schema_service_ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
})
- t.Run("request rule is already exist, should pass", func(t *testing.T) {
- respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
- ServiceId: "create_rule_group_ms_id",
- Rules: []*pb.AddOrUpdateServiceRule{
- {
- RuleType: "BLACK",
- Attribute: "ServiceName",
- Pattern: "Test*",
- Description: "test black",
- },
+ //
+ t.Run("add a schemaId in production env while schema editable is set",
func(t *testing.T) {
+ var (
+ serviceIdPro1 string
+ )
+ log.Info("register service")
+ respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId:
"add_a_schemaId_prod_schema_lock_ms",
+ ServiceName:
"add_a_schemaId_prod_schema_lock_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ Environment: pb.ENV_PROD,
},
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
- assert.Equal(t, 0, len(respAddRule.RuleIds))
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceIdPro1 = respCreateService.ServiceId
+
+ log.Info("add a schema with new schemaId, should pass")
+ schemas := []*pb.Schema{
+ {
+ SchemaId: "first_schemaId_ms",
+ Schema: "first_schema_ms",
+ Summary: "first0summary_ms",
+ },
+ }
+ respModifySchemas, err :=
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdPro1,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchemas.Response.GetCode())
+
+ respService, err :=
datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
+ ServiceId: serviceIdPro1,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respService.Response.GetCode())
+ assert.Equal(t, []string{"first_schemaId_ms"},
respService.Service.Schemas)
+
+ schemas = []*pb.Schema{
+ {
+ SchemaId: "second_schemaId_ms",
+ Schema: "second_schema_ms",
+ Summary: "second0summary_ms",
+ },
+ }
+ log.Info("schema edit not allowed, add a schema with new
schemaId should fail")
+
+ localMicroServiceDs := &mongo.DataSource{SchemaEditable: false}
+ respModifySchemas, err =
localMicroServiceDs.ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdPro1,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrUndefinedSchemaID,
respModifySchemas.Response.GetCode())
+
+ log.Info("schema edit allowed, add a schema with new schemaId,
should pass")
+ localMicroServiceDs = &mongo.DataSource{SchemaEditable: true}
+ respModifySchemas, err =
localMicroServiceDs.ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdPro1,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchemas.Response.GetCode())
+ })
+ //
+ t.Run("modify a schema in production env while schema editable is set",
func(t *testing.T) {
+ var (
+ serviceIdPro1 string
+ )
+ log.Info("register service")
+ respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId:
"modify_a_schema_prod_schema_lock_ms",
+ ServiceName:
"modify_a_schema_prod_schema_lock_service_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ Environment: pb.ENV_PROD,
+ },
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceIdPro1 = respCreateService.ServiceId
+
+ log.Info("add schemas, should pass")
+ schemas := []*pb.Schema{
+ {
+ SchemaId: "first_schemaId_ms",
+ Schema: "first_schema_ms",
+ Summary: "first0summary_ms",
+ },
+ }
+ respModifySchemas, err :=
datasource.Instance().ModifySchemas(getContext(), &pb.ModifySchemasRequest{
+ ServiceId: serviceIdPro1,
+ Schemas: schemas,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchemas.Response.GetCode())
+
+ respService, err :=
datasource.Instance().GetService(getContext(), &pb.GetServiceRequest{
+ ServiceId: serviceIdPro1,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, []string{"first_schemaId_ms"},
respService.Service.Schemas)
+
+ log.Info("schema edit not allowed, modify schema should fail")
+ localMicroServiceDs := &mongo.DataSource{SchemaEditable: false}
+ respModifySchema, err :=
localMicroServiceDs.ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: schemas[0].SchemaId,
+ Summary: schemas[0].Summary,
+ Schema: schemas[0].SchemaId,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrModifySchemaNotAllow,
respModifySchema.Response.GetCode())
+
+ log.Info("schema edit allowed, add a schema with new schemaId,
should pass")
+ localMicroServiceDs = &mongo.DataSource{SchemaEditable: true}
+ respModifySchema, err =
localMicroServiceDs.ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceIdPro1,
+ SchemaId: schemas[0].SchemaId,
+ Summary: schemas[0].Summary,
+ Schema: schemas[0].SchemaId,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respModifySchema.Response.GetCode())
})
}
-func TestRuleGet(t *testing.T) {
- t.Run("register service and rules, the request is valid, should pass",
func(t *testing.T) {
+func TestSchema_Exist(t *testing.T) {
+ var (
+ serviceId string
+ )
+
+ t.Run("register service and add schema", func(t *testing.T) {
+ log.Info("register service")
respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "get_rule_group_ms_id",
- AppId: "get_rule_group_ms",
- ServiceName: "get_rule_service_ms",
+ AppId: "query_schema_group_ms",
+ ServiceName: "query_schema_service_ms",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
+ Environment: pb.ENV_DEV,
},
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceId = respCreateService.ServiceId
- respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
- ServiceId: "get_rule_group_ms_id",
- Rules: []*pb.AddOrUpdateServiceRule{
- {
- RuleType: "BLACK",
- Attribute: "ServiceName",
- Pattern: "Test*",
- Description: "test BLACK",
- },
- },
+ log.Info("add schemas, should pass")
+ resp, err := datasource.Instance().ModifySchema(getContext(),
&pb.ModifySchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.ms",
+ Schema: "query schema ms",
+ Summary: "summary_ms",
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
- ruleId := respAddRule.RuleIds[0]
- assert.NotEqual(t, "", ruleId)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().ModifySchema(getContext(),
&pb.ModifySchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.no.summary.ms",
+ Schema: "query schema ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
})
- t.Run("get rule, when request is valid, should pass", func(t
*testing.T) {
- respGetRule, err :=
datasource.Instance().GetRules(getContext(), &pb.GetServiceRulesRequest{
- ServiceId: "get_rule_group_ms_id",
+
+ t.Run("check exists", func(t *testing.T) {
+ log.Info("check schema exist, should pass")
+ resp, err := datasource.Instance().ExistSchema(getContext(),
&pb.GetExistenceRequest{
+ Type: service.ExistTypeSchema,
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.ms",
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respGetRule.Response.GetCode())
- assert.Equal(t, 1, len(respGetRule.Rules))
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, "summary_ms", resp.Summary)
+
+ resp, err = datasource.Instance().ExistSchema(getContext(),
&pb.GetExistenceRequest{
+ Type: service.ExistTypeSchema,
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.ms",
+ AppId: "()",
+ ServiceName: "",
+ Version: "()",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ resp, err = datasource.Instance().ExistSchema(getContext(),
&pb.GetExistenceRequest{
+ Type: service.ExistTypeSchema,
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.no.summary.ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, "com.huawei.test.no.summary.ms", resp.SchemaId)
+ assert.Equal(t, "", resp.Summary)
})
}
-func TestRuleDelete(t *testing.T) {
- var ruleId string
- t.Run("register service and rules, when request is valid, should pass",
func(t *testing.T) {
+func TestSchema_Delete(t *testing.T) {
+ var (
+ serviceId string
+ )
+
+ t.Run("register service and instance", func(t *testing.T) {
respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "delete_rule_group_ms_id",
- AppId: "delete_rule_group_ms",
- ServiceName: "delete_rule_service_ms",
+ AppId: "delete_schema_group_ms",
+ ServiceName: "delete_schema_service_ms",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
@@ -482,84 +1996,212 @@ func TestRuleDelete(t *testing.T) {
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceId = respCreateService.ServiceId
- respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
- ServiceId: "delete_rule_group_ms_id",
- Rules: []*pb.AddOrUpdateServiceRule{
- {
- RuleType: "BLACK",
- Attribute: "ServiceName",
- Pattern: "Test*",
- Description: "test BLACK",
- },
- },
+ resp, err := datasource.Instance().ModifySchema(getContext(),
&pb.ModifySchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.ms",
+ Schema: "delete schema ms",
+ Summary: "summary_ms",
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
- ruleId = respAddRule.RuleIds[0]
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
})
- t.Run("delete rule, when request is valid, should pass", func(t
*testing.T) {
- resp, err := datasource.Instance().DeleteRule(getContext(),
&pb.DeleteServiceRulesRequest{
- ServiceId: "delete_rule_group_ms_id",
- RuleIds: []string{ruleId},
+
+ t.Run("test delete when request is invalid", func(t *testing.T) {
+ log.Info("schema id does not exist")
+ resp, err := datasource.Instance().DeleteSchema(getContext(),
&pb.DeleteSchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "none_exist_schema",
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.NotEqual(t, pb.ResponseSuccess, resp.Response.GetCode())
- respGetRule, err :=
datasource.Instance().GetRules(getContext(), &pb.GetServiceRulesRequest{
- ServiceId: "delete_rule_group_ms_id",
+ log.Info("service id does not exist")
+ resp, err = datasource.Instance().DeleteSchema(getContext(),
&pb.DeleteSchemaRequest{
+ ServiceId: "not_exist_service",
+ SchemaId: "com.huawei.test.ms",
+ })
+ assert.NoError(t, err)
+ assert.NotEqual(t, pb.ResponseSuccess, resp.Response.GetCode())
+ })
+ //
+ t.Run("test delete when request is valid", func(t *testing.T) {
+ resp, err := datasource.Instance().DeleteSchema(getContext(),
&pb.DeleteSchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.ms",
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- assert.Equal(t, 1, len(respGetRule.Rules))
+
+ respGet, err := datasource.Instance().GetSchema(getContext(),
&pb.GetSchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrSchemaNotExists,
respGet.Response.GetCode())
+
+ respExist, err :=
datasource.Instance().ExistSchema(getContext(), &pb.GetExistenceRequest{
+ Type: "schema",
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrSchemaNotExists,
respExist.Response.GetCode())
})
}
-func TestRuleUpdate(t *testing.T) {
- var ruleId string
- t.Run("create service and rules, when request is valid, should pass",
func(t *testing.T) {
+func TestSchema_Get(t *testing.T) {
+ var (
+ serviceId string
+ serviceId1 string
+ )
+
+ var (
+ schemaId1 string = "all_schema1_ms"
+ schemaId2 string = "all_schema2_ms"
+ schemaId3 string = "all_schema3_ms"
+ summary string = "this0is1a2test3ms"
+ schemaContent string = "the content is vary large"
+ )
+
+ t.Run("register service and instance", func(t *testing.T) {
respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "update_rule_group_ms_id",
- AppId: "update_rule_group_ms",
- ServiceName: "update_rule_service_ms",
+ AppId: "get_schema_group_ms",
+ ServiceName: "get_schema_service_ms",
Version: "1.0.0",
Level: "FRONT",
+ Schemas: []string{
+ "non-schema-content",
+ },
Status: pb.MS_UP,
+ Environment: pb.ENV_DEV,
},
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceId = respCreateService.ServiceId
- respAddRule, err := datasource.Instance().AddRule(getContext(),
&pb.AddServiceRulesRequest{
- ServiceId: "update_rule_group_ms_id",
- Rules: []*pb.AddOrUpdateServiceRule{
- {
- RuleType: "BLACK",
- Attribute: "ServiceName",
- Pattern: "Test*",
- Description: "test BLACK",
+ respCreateSchema, err :=
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.ms",
+ Schema: "get schema ms",
+ Summary: "schema0summary1ms",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateSchema.Response.GetCode())
+
+ respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "get_all_schema_ms",
+ ServiceName: "get_all_schema_ms",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Schemas: []string{
+ schemaId1,
+ schemaId2,
+ schemaId3,
},
+ Status: pb.MS_UP,
},
})
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respAddRule.Response.GetCode())
- assert.NotEqual(t, "", respAddRule.RuleIds[0])
- ruleId = respAddRule.RuleIds[0]
+ assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ serviceId1 = respCreateService.ServiceId
+ //
+ respPutData, err :=
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceId1,
+ SchemaId: schemaId2,
+ Schema: schemaContent,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respPutData.Response.GetCode())
+ //
+ respPutData, err =
datasource.Instance().ModifySchema(getContext(), &pb.ModifySchemaRequest{
+ ServiceId: serviceId1,
+ SchemaId: schemaId3,
+ Schema: schemaContent,
+ Summary: summary,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respPutData.Response.GetCode())
+ //
+ respGetAllSchema, err :=
datasource.Instance().GetAllSchemas(getContext(), &pb.GetAllSchemaRequest{
+ ServiceId: serviceId1,
+ WithSchema: false,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respGetAllSchema.Response.GetCode())
+ schemas := respGetAllSchema.Schemas
+ for _, schema := range schemas {
+ fmt.Println(schema.SchemaId)
+ if schema.SchemaId == schemaId1 && schema.SchemaId ==
schemaId2 {
+ assert.Empty(t, schema.Summary)
+ assert.Empty(t, schema.Schema)
+ }
+ if schema.SchemaId == schemaId3 {
+ assert.Equal(t, summary, schema.Summary)
+ assert.Empty(t, schema.Schema)
+ }
+ }
+ //
+ respGetAllSchema, err =
datasource.Instance().GetAllSchemas(getContext(), &pb.GetAllSchemaRequest{
+ ServiceId: serviceId1,
+ WithSchema: true,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respGetAllSchema.Response.GetCode())
+ schemas = respGetAllSchema.Schemas
+ for _, schema := range schemas {
+ switch schema.SchemaId {
+ case schemaId1:
+ assert.Empty(t, schema.Summary)
+ assert.Empty(t, schema.Schema)
+ case schemaId2:
+ assert.Empty(t, schema.Summary)
+ assert.Equal(t, schemaContent, schema.Schema)
+ case schemaId3:
+ assert.Equal(t, summary, schema.Summary)
+ assert.Equal(t, schemaContent, schema.Schema)
+ }
+ }
})
- t.Run("update rule, when request is valid, should pass", func(t
*testing.T) {
- resp, err := datasource.Instance().UpdateRule(getContext(),
&pb.UpdateServiceRuleRequest{
- ServiceId: "update_rule_group_ms_id",
- RuleId: ruleId,
- Rule: &pb.AddOrUpdateServiceRule{
- RuleType: "BLACK",
- Attribute: "AppId",
- Pattern: "Test*",
- Description: "test white update",
- },
+
+ t.Run("test get when request is invalid", func(t *testing.T) {
+ log.Info("service does not exist")
+ respGetSchema, err :=
datasource.Instance().GetSchema(getContext(), &pb.GetSchemaRequest{
+ ServiceId: "none_exist_service",
+ SchemaId: "com.huawei.test",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists,
respGetSchema.Response.GetCode())
+
+ respGetAllSchemas, err :=
datasource.Instance().GetAllSchemas(getContext(), &pb.GetAllSchemaRequest{
+ ServiceId: "none_exist_service",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists,
respGetAllSchemas.Response.GetCode())
+
+ log.Info("schema id doest not exist")
+ respGetSchema, err =
datasource.Instance().GetSchema(getContext(), &pb.GetSchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "none_exist_schema",
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrSchemaNotExists,
respGetSchema.Response.GetCode())
+ })
+
+ t.Run("test get when request is valid", func(t *testing.T) {
+ resp, err := datasource.Instance().GetSchema(getContext(),
&pb.GetSchemaRequest{
+ ServiceId: serviceId,
+ SchemaId: "com.huawei.test.ms",
})
assert.NoError(t, err)
assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ assert.Equal(t, "get schema ms", resp.Schema)
+ assert.Equal(t, "schema0summary1ms", resp.SchemaSummary)
+
})
}
diff --git a/datasource/mongo/util.go b/datasource/mongo/util.go
index 8de33ae..b7e045c 100644
--- a/datasource/mongo/util.go
+++ b/datasource/mongo/util.go
@@ -17,7 +17,16 @@
package mongo
-import "strings"
+import (
+ "context"
+ "strings"
+
+ "github.com/apache/servicecomb-service-center/datasource"
+ "github.com/apache/servicecomb-service-center/pkg/gopool"
+ "github.com/apache/servicecomb-service-center/pkg/util"
+ pb "github.com/go-chassis/cari/discovery"
+ "go.mongodb.org/mongo-driver/bson"
+)
func StringBuilder(data []string) string {
var str strings.Builder
@@ -30,3 +39,63 @@ func StringBuilder(data []string) string {
}
return str.String()
}
+
+func statistics(ctx context.Context, withShared bool) (*pb.Statistics, error) {
+ result := &pb.Statistics{
+ Services: &pb.StService{},
+ Instances: &pb.StInstance{},
+ Apps: &pb.StApp{},
+ }
+ domain := util.ParseDomain(ctx)
+ project := util.ParseProject(ctx)
+
+ filter := bson.M{ColumnDomain: domain, ColumnProject: project}
+
+ services, err := GetServices(ctx, filter)
+ if err != nil {
+ return nil, err
+ }
+
+ var svcIDs []string
+ var svcKeys []*pb.MicroServiceKey
+ for _, svc := range services {
+ svcIDs = append(svcIDs, svc.ServiceId)
+ svcKeys = append(svcKeys,
datasource.TransServiceToKey(util.ParseDomainProject(ctx), svc))
+ }
+ svcIDToNonVerKey := datasource.SetStaticServices(result, svcKeys,
svcIDs, withShared)
+
+ respGetInstanceCountByDomain := make(chan
datasource.GetInstanceCountByDomainResponse, 1)
+ gopool.Go(func(_ context.Context) {
+ getInstanceCountByDomain(ctx, svcIDToNonVerKey,
respGetInstanceCountByDomain)
+ })
+
+ instances, err := GetInstances(ctx, filter)
+ if err != nil {
+ return nil, err
+ }
+ var instIDs []string
+ for _, inst := range instances {
+ instIDs = append(instIDs, inst.InstanceInfo.ServiceId)
+ }
+ datasource.SetStaticInstances(result, svcIDToNonVerKey, instIDs)
+ data := <-respGetInstanceCountByDomain
+ close(respGetInstanceCountByDomain)
+ if data.Err != nil {
+ return nil, data.Err
+ }
+ result.Instances.CountByDomain = data.CountByDomain
+ return result, nil
+}
+
+func getInstanceCountByDomain(ctx context.Context, svcIDToNonVerKey
map[string]string, resp chan datasource.GetInstanceCountByDomainResponse) {
+ ret := datasource.GetInstanceCountByDomainResponse{}
+ for _, sid := range svcIDToNonVerKey {
+ num, err := GetInstanceCountOfOneService(ctx, sid)
+ if err != nil {
+ ret.Err = err
+ return
+ }
+ ret.CountByDomain = ret.CountByDomain + num
+ }
+ resp <- ret
+}
diff --git a/datasource/ms_util.go b/datasource/ms_util.go
index 0090e33..769e544 100644
--- a/datasource/ms_util.go
+++ b/datasource/ms_util.go
@@ -17,7 +17,16 @@
package datasource
-import "github.com/go-chassis/cari/discovery"
+import (
+ "github.com/apache/servicecomb-service-center/pkg/util"
+ "github.com/apache/servicecomb-service-center/server/core"
+ "github.com/go-chassis/cari/discovery"
+)
+
+type GetInstanceCountByDomainResponse struct {
+ Err error
+ CountByDomain int64
+}
func SetServiceDefaultValue(service *discovery.MicroService) {
if len(service.AppId) == 0 {
@@ -33,3 +42,63 @@ func SetServiceDefaultValue(service *discovery.MicroService)
{
service.Status = discovery.MS_UP
}
}
+
+// SetStaticServices calculate the service/application num under a
domainProject
+func SetStaticServices(statistics *discovery.Statistics, svcKeys
[]*discovery.MicroServiceKey, svcIDs []string, withShared bool)
map[string]string {
+ l := len(svcKeys)
+ app := make(map[string]struct{}, l)
+ svcWithNonVersion := make(map[string]struct{}, l)
+ svcIDToNonVerKey := make(map[string]string, l)
+ for index, svc := range svcKeys {
+ if !withShared && core.IsGlobal(svc) {
+ continue
+ }
+ if _, ok := app[svc.AppId]; !ok {
+ app[svc.AppId] = struct{}{}
+ }
+ svc.Version = ""
+ svcWithNonVersionKey := generateServiceKey(svc)
+ if _, ok := svcWithNonVersion[svcWithNonVersionKey]; !ok {
+ svcWithNonVersion[svcWithNonVersionKey] = struct{}{}
+ }
+ svcIDToNonVerKey[svcIDs[index]] = svcWithNonVersionKey
+ }
+ statistics.Services.Count = int64(len(svcWithNonVersion))
+ statistics.Apps.Count = int64(len(app))
+ return svcIDToNonVerKey
+}
+
+// SetStaticInstances calculate the instance/onlineService num under a
domainProject
+func SetStaticInstances(statistics *discovery.Statistics, svcIDToNonVerKey
map[string]string, instServiceIDs []string) {
+ onlineServices := make(map[string]struct{}, len(instServiceIDs))
+ for _, sid := range instServiceIDs {
+ key, ok := svcIDToNonVerKey[sid]
+ if !ok {
+ continue
+ }
+ statistics.Instances.Count++
+ if _, ok := onlineServices[key]; !ok {
+ onlineServices[key] = struct{}{}
+ }
+ }
+ statistics.Services.OnlineCount = int64(len(onlineServices))
+}
+
+func generateServiceKey(key *discovery.MicroServiceKey) string {
+ return util.StringJoin([]string{
+ key.Environment,
+ key.AppId,
+ key.ServiceName,
+ key.Version,
+ }, "/")
+}
+
+func TransServiceToKey(domainProject string, service *discovery.MicroService)
*discovery.MicroServiceKey {
+ return &discovery.MicroServiceKey{
+ Tenant: domainProject,
+ Environment: service.Environment,
+ AppId: service.AppId,
+ ServiceName: service.ServiceName,
+ Version: service.Version,
+ }
+}