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 a0a2104 [SCB-2094] add dep UT, implement dep query interface (#776)
a0a2104 is described below
commit a0a2104115578c3e1baa28e1970e8fdfedfc4c06
Author: xzccfzy <[email protected]>
AuthorDate: Tue Dec 15 10:01:12 2020 +0800
[SCB-2094] add dep UT, implement dep query interface (#776)
---
datasource/mongo/database.go | 3 +
datasource/mongo/dep.go | 203 +--------------
datasource/mongo/dep_test.go | 484 ++++++++++++++++++++++++++---------
datasource/mongo/dependency_query.go | 474 ++++++++++++++++++++++++++++++++++
datasource/mongo/ms.go | 58 +++--
5 files changed, 877 insertions(+), 345 deletions(-)
diff --git a/datasource/mongo/database.go b/datasource/mongo/database.go
index 3bfdf25..9cbcfb5 100644
--- a/datasource/mongo/database.go
+++ b/datasource/mongo/database.go
@@ -76,6 +76,9 @@ const (
ColumnRuleInfo = "ruleinfo"
ColumnInstanceInfo = "instanceinfo"
ColumnInstanceID = "instanceid"
+ ColumnConsumerID = "consumerid"
+ ColumnMongoID = "_id"
+ ColumnTenant = "tenant"
)
type Service struct {
diff --git a/datasource/mongo/dep.go b/datasource/mongo/dep.go
index 6a1eef2..0566c5b 100644
--- a/datasource/mongo/dep.go
+++ b/datasource/mongo/dep.go
@@ -19,13 +19,11 @@ package mongo
import (
"context"
+ "fmt"
pb "github.com/go-chassis/cari/discovery"
"go.mongodb.org/mongo-driver/bson"
- "fmt"
- "strings"
-
"github.com/apache/servicecomb-service-center/datasource"
"github.com/apache/servicecomb-service-center/datasource/mongo/client"
"github.com/apache/servicecomb-service-center/pkg/log"
@@ -33,6 +31,7 @@ import (
)
func (ds *DataSource) SearchProviderDependency(ctx context.Context, request
*pb.GetDependenciesRequest) (*pb.GetProDependenciesResponse, error) {
+ domainProject := util.ParseDomainProject(ctx)
providerServiceID := request.ServiceId
filter := GeneratorServiceFilter(ctx, providerServiceID)
provider, err := GetService(ctx, filter)
@@ -47,7 +46,8 @@ func (ds *DataSource) SearchProviderDependency(ctx
context.Context, request *pb.
}, nil
}
- services, err := GetDependencyProviders(ctx, provider.ServiceInfo,
request)
+ dr := NewProviderDependencyRelation(ctx, domainProject,
provider.ServiceInfo)
+ services, err :=
dr.GetDependencyConsumers(ToDependencyFilterOptions(request)...)
if err != nil {
log.Error(fmt.Sprintf("GetProviderDependencies failed, provider
is %s/%s/%s/%s",
provider.ServiceInfo.Environment,
provider.ServiceInfo.AppId, provider.ServiceInfo.ServiceName,
provider.ServiceInfo.Version), err)
@@ -63,6 +63,7 @@ func (ds *DataSource) SearchProviderDependency(ctx
context.Context, request *pb.
}
func (ds *DataSource) SearchConsumerDependency(ctx context.Context, request
*pb.GetDependenciesRequest) (*pb.GetConDependenciesResponse, error) {
+ domainProject := util.ParseDomainProject(ctx)
consumerID := request.ServiceId
filter := GeneratorServiceFilter(ctx, consumerID)
@@ -78,7 +79,8 @@ func (ds *DataSource) SearchConsumerDependency(ctx
context.Context, request *pb.
}, nil
}
- services, err := GetDependencyProviders(ctx, consumer.ServiceInfo,
request)
+ dr := NewConsumerDependencyRelation(ctx, domainProject,
consumer.ServiceInfo)
+ services, err :=
dr.GetDependencyProviders(ToDependencyFilterOptions(request)...)
if err != nil {
log.Error(fmt.Sprintf("GetConsumerDependencies failed, consumer
is %s/%s/%s/%s",
consumer.ServiceInfo.Environment,
consumer.ServiceInfo.AppId, consumer.ServiceInfo.ServiceName,
consumer.ServiceInfo.Version), err)
@@ -152,197 +154,6 @@ func (ds *DataSource) DeleteDependency() {
panic("implement me")
}
-func GetDependencyProviders(ctx context.Context, consumer *pb.MicroService,
request *pb.GetDependenciesRequest) ([]*pb.MicroService, error) {
- keys, err := GetProviderKeys(ctx, consumer)
- if err != nil {
- return nil, err
- }
-
- services := make([]*pb.MicroService, 0, len(keys))
-
- for _, key := range keys {
- domainProject := util.ParseDomainProject(ctx)
- if request.SameDomain && key.Tenant != domainProject {
- continue
- }
-
- providerIDs, err := ParseDependencyRule(ctx, key)
- if err != nil {
- return nil, err
- }
-
- if key.ServiceName == "*" {
- services = services[:0]
- }
-
- for _, providerID := range providerIDs {
- filter := GeneratorServiceFilter(ctx, providerID)
- provider, err := GetService(ctx, filter)
- if err != nil {
- log.Warn(fmt.Sprintf("get provider[%s/%s/%s/%s]
failed",
- key.Environment, key.AppId,
key.ServiceName, key.Version))
- continue
- }
- if provider == nil {
- log.Warn(fmt.Sprintf("provider[%s/%s/%s/%s]
does not exist",
- key.Environment, key.AppId,
key.ServiceName, key.Version))
- continue
- }
- if request.NoSelf && providerID == consumer.ServiceId {
- continue
- }
- services = append(services, provider.ServiceInfo)
- }
-
- if key.ServiceName == "*" {
- break
- }
- }
-
- return services, nil
-}
-
-func GetProviderKeys(ctx context.Context, consumer *pb.MicroService)
([]*pb.MicroServiceKey, error) {
- if consumer == nil {
- return nil, ErrInvalidConsumer
- }
- domainProject := util.ParseDomainProject(ctx)
- consumerMicroServiceKey := &pb.MicroServiceKey{
- Tenant: domainProject,
- Environment: consumer.Environment,
- AppId: consumer.AppId,
- ServiceName: consumer.ServiceName,
- Alias: consumer.Alias,
- Version: consumer.Version,
- }
-
- filter := GenerateConsumerDependencyRuleKey(ctx,
consumerMicroServiceKey)
-
- findRes, err := client.GetMongoClient().Find(ctx, CollectionDep, filter)
- if err != nil {
- return nil, err
- }
- var services []*pb.MicroServiceKey
- for findRes.Next(ctx) {
- var tempMongoDep Dependency
- err := findRes.Decode(&tempMongoDep)
- if err != nil {
- return nil, err
- }
- providers := tempMongoDep.DependencyInfo.Providers
- services = append(services, providers...)
- }
- return services, nil
-}
-
-func GenerateConsumerDependencyRuleKey(ctx context.Context, in
*pb.MicroServiceKey) bson.M {
-
- domain := util.ParseDomain(ctx)
- project := util.ParseProject(ctx)
- if in == nil {
- return bson.M{
- ColumnDomain: domain,
- ColumnProject: project,
- }
- }
- if in.ServiceName == "*" {
- return bson.M{
- ColumnDomain: domain,
- ColumnProject: project,
- StringBuilder([]string{ColumnDependencyInfo,
ColumnConsumer, ColumnEnv}): in.Environment,
- }
- }
- return bson.M{
- ColumnDomain: domain,
- ColumnProject: project,
- StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer,
ColumnEnv}): in.Environment,
- StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer,
ColumnAppID}): in.AppId,
- StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer,
ColumnVersion}): in.Version,
- }
-}
-
-func ParseDependencyRule(ctx context.Context, dependencyRule
*pb.MicroServiceKey) (serviceIDs []string, err error) {
- switch {
- case dependencyRule.ServiceName == "*":
- splited := strings.Split(dependencyRule.Tenant, "/")
- filter := bson.M{
- ColumnDomain: splited[0],
- ColumnProject: splited[1],
- StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):
dependencyRule.Environment}
- findRes, err := client.GetMongoClient().Find(ctx,
CollectionService, filter)
- if err != nil {
- return nil, err
- }
- for findRes.Next(ctx) {
- var service Service
- err = findRes.Decode(&service)
- if err != nil {
- return nil, err
- }
- serviceIDs = append(serviceIDs,
service.ServiceInfo.ServiceId)
- }
- default:
- serviceIDs, err = FindServiceIds(ctx, dependencyRule)
- }
- return
-}
-
-func FindServiceIds(ctx context.Context, key *pb.MicroServiceKey) ([]string,
error) {
- versionRule := key.Version
- splited := strings.Split(key.Tenant, "/")
- if len(versionRule) == 0 {
- return nil, nil
- }
- rangeIdx := strings.Index(versionRule, "-")
- switch {
- case versionRule == "latest":
- filter := bson.M{
- ColumnDomain: splited[0],
- ColumnProject: splited[1]}
- return GetFilterVersionService(ctx, filter)
- case versionRule[len(versionRule)-1:] == "+":
- start := versionRule[:len(versionRule)-1]
- filter := bson.M{
- ColumnDomain: splited[0],
- ColumnProject: splited[1],
- StringBuilder([]string{ColumnServiceInfo,
ColumnVersion}): bson.M{"$gte": start}}
- return GetFilterVersionService(ctx, filter)
- case rangeIdx > 0:
- start := versionRule[:rangeIdx]
- end := versionRule[rangeIdx+1:]
- filter := bson.M{
- ColumnDomain: splited[0],
- ColumnProject: splited[1],
- StringBuilder([]string{ColumnServiceInfo,
ColumnVersion}): bson.M{"$gts": start, "$lt": end}}
- return GetFilterVersionService(ctx, filter)
- default:
- filter := bson.M{
- ColumnDomain: splited[0],
- ColumnProject: splited[1],
- StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):
key.Environment,
- StringBuilder([]string{ColumnServiceInfo,
ColumnAppID}): key.AppId,
- StringBuilder([]string{ColumnServiceInfo,
ColumnServiceName}): key.ServiceName,
- StringBuilder([]string{ColumnServiceInfo,
ColumnVersion}): key.Version}
- return GetFilterVersionService(ctx, filter)
- }
-}
-
-func GetFilterVersionService(ctx context.Context, m bson.M) (serviceIDs
[]string, err error) {
- findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m)
- if err != nil {
- return nil, err
- }
- for findRes.Next(ctx) {
- var service Service
- err = findRes.Decode(&service)
- if err != nil {
- return nil, err
- }
- serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
- }
- return
-}
-
func GetServiceID(ctx context.Context, key *pb.MicroServiceKey) (serviceID
string, err error) {
domain := util.ParseDomain(ctx)
project := util.ParseProject(ctx)
diff --git a/datasource/mongo/dep_test.go b/datasource/mongo/dep_test.go
index 77bdc06..2b0f4fb 100644
--- a/datasource/mongo/dep_test.go
+++ b/datasource/mongo/dep_test.go
@@ -25,182 +25,237 @@ import (
"github.com/stretchr/testify/assert"
)
-func TestDep_Creat(t *testing.T) {
-
+func Test_Creat(t *testing.T) {
var (
consumerId1 string
+ consumerId2 string
consumerId3 string
)
- t.Run("creat service, when request is valid, should not pass", func(t
*testing.T) {
- respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ t.Run("create service, should be passed", func(t *testing.T) {
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "dep1",
- AppId: "create_dep_group",
- ServiceName: "create_dep_consumer",
+ AppId: "dep_create_dep_group",
+ ServiceName: "dep_create_dep_consumer",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
},
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
- consumerId1 = respCreateService.ServiceId
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ consumerId1 = resp.ServiceId
- respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "dep2",
- AppId: "create_dep_group",
- ServiceName: "create_dep_consumer_all",
+ AppId: "dep_create_dep_group",
+ ServiceName: "dep_create_dep_consumer_all",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
},
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
- consumerId3 = respCreateService.ServiceId
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ consumerId3 = resp.ServiceId
- respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "dep3",
Environment: pb.ENV_PROD,
- AppId: "create_dep_group",
- ServiceName: "create_dep_consumer",
+ AppId: "dep_create_dep_group",
+ ServiceName: "dep_create_dep_consumer",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
},
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ consumerId2 = resp.ServiceId
- respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "dep4",
- AppId: "create_dep_group",
- ServiceName: "create_dep_provider",
+ AppId: "dep_create_dep_group",
+ ServiceName: "dep_create_dep_provider",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
},
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "dep5",
- AppId: "create_dep_group",
- ServiceName: "create_dep_provider",
+ AppId: "dep_create_dep_group",
+ ServiceName: "dep_create_dep_provider",
Version: "1.0.1",
Level: "FRONT",
Status: pb.MS_UP,
},
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "dep6",
Environment: pb.ENV_PROD,
- AppId: "create_dep_group",
- ServiceName: "create_dep_provider",
+ AppId: "dep_create_dep_group",
+ ServiceName: "dep_create_dep_provider",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
},
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
})
- t.Run("create dep, when request is valid, should be passed", func(t
*testing.T) {
+ t.Run("add dep and search, when request is invalid, should be failed",
func(t *testing.T) {
+ consumer := &pb.MicroServiceKey{
+ AppId: "dep_create_dep_group",
+ ServiceName: "dep_create_dep_consumer",
+ Version: "1.0.0",
+ }
+ providers := []*pb.MicroServiceKey{
+ {
+ AppId: "dep_create_dep_group",
+ ServiceName: "dep_create_dep_provider",
+ Version: "1.0.0",
+ },
+ }
- respCreateDependency, err :=
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ // consumer does not exist
+ resp, err :=
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
{
Consumer: &pb.MicroServiceKey{
- ServiceName: "create_dep_consumer",
- AppId: "create_dep_group",
+ AppId: "noexistapp",
+ ServiceName: "noexistservice",
Version: "1.0.0",
},
+ Providers: providers,
+ },
+ }, false)
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists, resp.GetCode())
+
+ // provider in diff env
+ resp, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ {
+ Consumer: consumer,
Providers: []*pb.MicroServiceKey{
{
- AppId: "create_dep_group",
- ServiceName:
"create_dep_provider",
+ Environment: pb.ENV_PROD,
+ AppId:
"dep_service_group_provider",
+ ServiceName:
"dep_service_name_provider",
Version: "latest",
},
},
},
}, false)
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateDependency.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
- respPro, err :=
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ // consumer in diff env
+ consumer.Environment = pb.ENV_PROD
+ resp, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ {
+ Consumer: consumer,
+ Providers: []*pb.MicroServiceKey{
+ {
+ AppId:
"dep_service_group_provider",
+ ServiceName:
"dep_service_name_provider",
+ Version: "latest",
+ },
+ },
+ },
+ }, false)
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+ respCon, err :=
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
ServiceId: consumerId1,
})
+ assert.NotNil(t, respCon)
+ assert.NoError(t, err)
+
+ respCon, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ ServiceId: consumerId2,
+ })
+ assert.NotNil(t, respCon)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
- assert.NotEqual(t, "1.0.1", respPro.Providers[0].Version)
+ })
+
+ t.Run("add dep and search, when request is valid, should be passed",
func(t *testing.T) {
+ consumer := &pb.MicroServiceKey{
+ ServiceName: "dep_create_dep_consumer",
+ AppId: "dep_create_dep_group",
+ Version: "1.0.0",
+ }
- respCreateDependency, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ // add latest
+ resp, err :=
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
{
- Consumer: &pb.MicroServiceKey{
- ServiceName: "create_dep_consumer",
- AppId: "create_dep_group",
- Version: "1.0.0",
- },
+ Consumer: consumer,
Providers: []*pb.MicroServiceKey{
{
- AppId: "create_dep_group",
- ServiceName:
"create_dep_provider",
- Version: "1.0.0+",
+ AppId:
"dep_create_dep_group",
+ ServiceName:
"dep_create_dep_provider",
+ Version: "latest",
},
},
},
}, false)
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateDependency.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
- respPro, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ respPro, err :=
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
ServiceId: consumerId1,
})
+ assert.NotNil(t, respPro)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
- assert.NotEqual(t, "1.0.1", respPro.Providers[0].Version)
+ assert.NotEqual(t, 0, len(respPro.Providers))
+ assert.Equal(t, "1.0.1", respPro.Providers[0].Version)
- respCreateDependency, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ // add 1.0.0+
+ resp, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
{
- Consumer: &pb.MicroServiceKey{
- ServiceName: "create_dep_consumer",
- AppId: "create_dep_group",
- Version: "1.0.0",
- },
+ Consumer: consumer,
Providers: []*pb.MicroServiceKey{
{
- AppId: "create_dep_group",
- ServiceName:
"create_dep_provider",
+ AppId:
"dep_create_dep_group",
+ ServiceName:
"dep_create_dep_provider",
Version: "1.0.0+",
},
},
},
}, false)
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateDependency.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
respPro, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
ServiceId: consumerId1,
})
+ assert.NotNil(t, respPro)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
- assert.NotEqual(t, 2, len(respPro.Providers))
- respCreateDependency, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ // add *
+ resp, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
{
Consumer: &pb.MicroServiceKey{
- ServiceName: "create_dep_consumer_all",
- AppId: "create_dep_group",
+ ServiceName:
"dep_create_dep_consumer_all",
+ AppId: "dep_create_dep_group",
Version: "1.0.0",
},
Providers: []*pb.MicroServiceKey{
@@ -210,40 +265,40 @@ func TestDep_Creat(t *testing.T) {
},
},
}, false)
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateDependency.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
respPro, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
ServiceId: consumerId3,
})
+ assert.NotNil(t, respPro)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
- assert.NotEqual(t, 0, len(respPro.Providers))
+ assert.Equal(t, 0, len(respPro.Providers))
- respCreateDependency, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ // clean all
+ resp, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
{
Consumer: &pb.MicroServiceKey{
- ServiceName: "create_dep_consumer_all",
- AppId: "create_dep_group",
+ ServiceName:
"dep_create_dep_consumer_all",
+ AppId: "dep_create_dep_group",
Version: "1.0.0",
},
Providers: nil,
},
}, false)
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateDependency.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
- respCreateDependency, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ // add multiple providers
+ resp, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
{
- Consumer: &pb.MicroServiceKey{
- ServiceName: "create_dep_consumer",
- AppId: "create_dep_group",
- Version: "1.0.0",
- },
+ Consumer: consumer,
Providers: []*pb.MicroServiceKey{
{
- AppId: "create_dep_group",
- ServiceName:
"create_dep_provider",
+ AppId:
"dep_create_dep_group",
+ ServiceName:
"dep_create_dep_provider",
Version: "1.0.0",
},
{
@@ -252,100 +307,281 @@ func TestDep_Creat(t *testing.T) {
},
},
}, false)
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateDependency.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
- respCreateDependency, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ // add 1.0.0-2.0.0 to override *
+ resp, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
{
- Consumer: &pb.MicroServiceKey{
- ServiceName: "create_dep_consumer",
- AppId: "create_dep_group",
- Version: "1.0.0",
- },
+ Consumer: consumer,
Providers: []*pb.MicroServiceKey{
{
- AppId: "create_dep_group",
- ServiceName:
"create_dep_provider",
+ AppId:
"dep_create_dep_group",
+ ServiceName:
"dep_create_dep_provider",
Version: "1.0.0-1.0.1",
},
},
},
}, false)
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+ respPro, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ ServiceId: consumerId1,
+ })
+ assert.NotNil(t, respPro)
+ assert.NoError(t, err)
+ assert.Equal(t, "1.0.1", respPro.Providers[0].Version)
+
+ // add not override
+ respAdd, err :=
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ {
+ Consumer: consumer,
+ Providers: []*pb.MicroServiceKey{
+ {
+ AppId:
"dep_create_dep_group",
+ ServiceName:
"dep_create_dep_provider",
+ Version: "1.0.0-3.0.0",
+ },
+ },
+ },
+ }, false)
+ assert.NotNil(t, respAdd)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, respAdd.GetCode())
+
+ respPro, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ ServiceId: consumerId1,
+ })
+ assert.NotNil(t, respPro)
+ assert.NoError(t, err)
+
+ // add provider is empty
+ resp, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ {
+ Consumer: consumer,
+ Providers: []*pb.MicroServiceKey{},
+ },
+ }, false)
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
+
+ resp, err =
datasource.Instance().AddOrUpdateDependencies(getContext(),
[]*pb.ConsumerDependency{
+ {
+ Consumer: consumer,
+ },
+ }, false)
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateDependency.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.GetCode())
respPro, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
ServiceId: consumerId1,
})
+ assert.NotNil(t, respPro)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
- assert.Equal(t, "1.0.0", respPro.Providers[0].Version)
})
}
-func TestDep_Get(t *testing.T) {
-
+func Test_Get(t *testing.T) {
var (
consumerId1 string
providerId1 string
+ providerId2 string
)
- t.Run("create service, when request is valid, should be passed", func(t
*testing.T) {
- respCreateService, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ t.Run("create service, should be passed", func(t *testing.T) {
+ resp, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "dep7",
- AppId: "get_dep_group",
- ServiceName: "get_dep_consumer",
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_consumer",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
},
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
- consumerId1 = respCreateService.ServiceId
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ consumerId1 = resp.ServiceId
- respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "dep8",
- AppId: "get_dep_group",
- ServiceName: "get_dep_provider",
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_provider",
Version: "1.0.0",
Level: "FRONT",
Status: pb.MS_UP,
},
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
- providerId1 = respCreateService.ServiceId
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ providerId1 = resp.ServiceId
- respCreateService, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ resp, err = datasource.Instance().RegisterService(getContext(),
&pb.CreateServiceRequest{
Service: &pb.MicroService{
- ServiceId: "dep9",
- AppId: "get_dep_group",
- ServiceName: "get_dep_provider",
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_provider",
Version: "2.0.0",
Level: "FRONT",
Status: pb.MS_UP,
},
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess,
respCreateService.Response.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ providerId2 = resp.ServiceId
})
- t.Run("execute 'search dep' operation, when request is valid,should be
passed", func(t *testing.T) {
- respPro, err :=
datasource.Instance().SearchProviderDependency(getContext(),
&pb.GetDependenciesRequest{
+ t.Run("search dep, when request is valid, should be passed", func(t
*testing.T) {
+ //get provider
+ resp, err :=
datasource.Instance().SearchProviderDependency(getContext(),
&pb.GetDependenciesRequest{
ServiceId: providerId1,
})
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, respPro.Response.GetCode())
- respCon, err :=
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ //get consumer
+ resp, err =
datasource.Instance().SearchProviderDependency(getContext(),
&pb.GetDependenciesRequest{
+ ServiceId: consumerId1,
+ })
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ })
+
+ t.Run("when after finding instance, should created dependencies between
C and P", func(t *testing.T) {
+ // find provider
+ resp, err := datasource.Instance().FindInstances(getContext(),
&pb.FindInstancesRequest{
+ ConsumerServiceId: consumerId1,
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_provider",
+ VersionRule: "1.0.0+",
+ })
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ // get consumer's deps
+ respGetP, err :=
datasource.Instance().SearchProviderDependency(getContext(),
&pb.GetDependenciesRequest{
+ ServiceId: providerId1,
+ })
+ assert.NotNil(t, respGetP)
+ assert.NoError(t, err)
+
+ // get provider's deps
+ respGetC, err :=
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ ServiceId: consumerId1,
+ })
+ assert.NotNil(t, respGetC)
+ assert.NoError(t, err)
+
+ // get self deps
+ resp, err = datasource.Instance().FindInstances(getContext(),
&pb.FindInstancesRequest{
+ ConsumerServiceId: consumerId1,
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_consumer",
+ VersionRule: "1.0.0+",
+ })
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ respGetC, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
ServiceId: consumerId1,
+ NoSelf: true,
+ })
+ assert.NotNil(t, respGetC)
+ assert.NoError(t, err)
+
+ // find before provider register
+ resp, err = datasource.Instance().FindInstances(getContext(),
&pb.FindInstancesRequest{
+ ConsumerServiceId: providerId2,
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_finder",
+ VersionRule: "1.0.0+",
+ })
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ErrServiceNotExists, resp.Response.GetCode())
+
+ respCreateF, err :=
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_finder",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
+ })
+ assert.NotNil(t, respCreateF)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateF.Response.GetCode())
+ finder1 := respCreateF.ServiceId
+
+ resp, err = datasource.Instance().FindInstances(getContext(),
&pb.FindInstancesRequest{
+ ConsumerServiceId: providerId2,
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_finder",
+ VersionRule: "1.0.0+",
+ })
+ assert.NotNil(t, resp)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+
+ respGetC, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ ServiceId: providerId2,
+ })
+ assert.NotNil(t, respGetC)
+ assert.NoError(t, err)
+
+ // find after delete micro service
+ respDelP, err :=
datasource.Instance().UnregisterService(getContext(), &pb.DeleteServiceRequest{
+ ServiceId: finder1, Force: true,
+ })
+ assert.NotNil(t, respDelP)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess, respDelP.Response.GetCode())
+
+ respGetC, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ ServiceId: providerId2,
+ })
+ assert.NotNil(t, respGetC)
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(respGetC.Providers))
+
+ respCreateF, err =
datasource.Instance().RegisterService(getContext(), &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ ServiceId: finder1,
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_finder",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
})
+ assert.NotNil(t, respCreateF)
+ assert.NoError(t, err)
+ assert.Equal(t, pb.ResponseSuccess,
respCreateF.Response.GetCode())
+ resp, err = datasource.Instance().FindInstances(getContext(),
&pb.FindInstancesRequest{
+ ConsumerServiceId: providerId2,
+ AppId: "dep_get_dep_group",
+ ServiceName: "dep_get_dep_finder",
+ VersionRule: "1.0.0+",
+ })
+ assert.NotNil(t, resp)
assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, respCon.Response.GetCode())
+ assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
+ respGetC, err =
datasource.Instance().SearchConsumerDependency(getContext(),
&pb.GetDependenciesRequest{
+ ServiceId: providerId2,
+ })
+ assert.NotNil(t, respGetC)
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(respGetC.Providers))
})
}
diff --git a/datasource/mongo/dependency_query.go
b/datasource/mongo/dependency_query.go
new file mode 100644
index 0000000..8025aba
--- /dev/null
+++ b/datasource/mongo/dependency_query.go
@@ -0,0 +1,474 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mongo
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/apache/servicecomb-service-center/datasource/mongo/client"
+ "github.com/apache/servicecomb-service-center/pkg/log"
+ pb "github.com/go-chassis/cari/discovery"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo/options"
+)
+
+type DependencyRelation struct {
+ ctx context.Context
+ domainProject string
+ consumer *pb.MicroService
+ provider *pb.MicroService
+}
+
+type DependencyRelationFilterOpt struct {
+ SameDomainProject bool
+ NonSelf bool
+}
+
+type DependencyRelationFilterOption func(opt DependencyRelationFilterOpt)
DependencyRelationFilterOpt
+
+func NewConsumerDependencyRelation(ctx context.Context, domainProject string,
consumer *pb.MicroService) *DependencyRelation {
+ return NewDependencyRelation(ctx, domainProject, consumer, nil)
+}
+
+func NewProviderDependencyRelation(ctx context.Context, domainProject string,
provider *pb.MicroService) *DependencyRelation {
+ return NewDependencyRelation(ctx, domainProject, nil, provider)
+}
+
+func NewDependencyRelation(ctx context.Context, domainProject string, consumer
*pb.MicroService, provider *pb.MicroService) *DependencyRelation {
+ return &DependencyRelation{
+ ctx: ctx,
+ domainProject: domainProject,
+ consumer: consumer,
+ provider: provider,
+ }
+}
+
+func (dr *DependencyRelation) GetDependencyProviders(opts
...DependencyRelationFilterOption) ([]*pb.MicroService, error) {
+ keys, err := dr.getProviderKeys()
+ if err != nil {
+ return nil, err
+ }
+ services := make([]*pb.MicroService, 0, len(keys))
+ op := ToDependencyRelationFilterOpt(opts...)
+
+ for _, key := range keys {
+ if op.SameDomainProject && key.Tenant != dr.domainProject {
+ continue
+ }
+ providerIDs, err := dr.parseDependencyRule(key)
+
+ if err != nil {
+ return nil, err
+ }
+
+ if key.ServiceName == "*" {
+ services = services[:0]
+ }
+
+ for _, providerID := range providerIDs {
+ filter := GeneratorServiceFilter(dr.ctx, providerID)
+ provider, err := GetService(dr.ctx, filter)
+ if err != nil {
+ log.Warn(fmt.Sprintf("get provider[%s/%s/%s/%s]
failed",
+ key.Environment, key.AppId,
key.ServiceName, key.Version))
+ continue
+ }
+ if provider == nil {
+ log.Warn(fmt.Sprintf("provider[%s/%s/%s/%s]
does not exist",
+ key.Environment, key.AppId,
key.ServiceName, key.Version))
+ continue
+ }
+ if op.NonSelf && providerID == dr.consumer.ServiceId {
+ continue
+ }
+ services = append(services, provider.ServiceInfo)
+ }
+ if key.ServiceName == "*" {
+ break
+ }
+ }
+ return services, nil
+}
+
+func (dr *DependencyRelation) GetDependencyConsumers(opts
...DependencyRelationFilterOption) ([]*pb.MicroService, error) {
+ consumerDependAllList, err := dr.GetDependencyConsumersOfProvider()
+ if err != nil {
+ log.Error(fmt.Sprintf("get service[%s]'s consumers failed",
dr.provider.ServiceId), err)
+ return nil, err
+ }
+ consumers := make([]*pb.MicroService, 0)
+ op := ToDependencyRelationFilterOpt(opts...)
+ for _, consumer := range consumerDependAllList {
+ if op.SameDomainProject && consumer.Tenant != dr.domainProject {
+ continue
+ }
+ service, err := dr.GetServiceByMicroServiceKey(consumer)
+ if err != nil {
+ return nil, err
+ }
+ if service == nil {
+ log.Warn(fmt.Sprintf("consumer[%s/%s/%s/%s] does not
exist",
+ consumer.Environment, consumer.AppId,
consumer.ServiceName, consumer.Version))
+ continue
+ }
+ if op.NonSelf && service.ServiceId == dr.provider.ServiceId {
+ continue
+ }
+ consumers = append(consumers, service)
+ }
+ return consumers, nil
+}
+
+func (dr *DependencyRelation) GetDependencyConsumersOfProvider()
([]*pb.MicroServiceKey, error) {
+ if dr.provider == nil {
+ return nil, ErrInvalidConsumer
+ }
+ consumerDependAllList, err := dr.getConsumerOfDependAllServices()
+ if err != nil {
+ log.Error(fmt.Sprintf("get consumers that depend on all
services failed, %s", dr.provider.ServiceId), err)
+ return nil, err
+ }
+ return consumerDependAllList, nil
+}
+
+func (dr *DependencyRelation) GetServiceByMicroServiceKey(service
*pb.MicroServiceKey) (*pb.MicroService, error) {
+ filter, err := MicroServiceKeyFilter(service)
+ if err != nil {
+ log.Error("get serivce failed", err)
+ return nil, err
+ }
+ findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionService,
filter)
+ if err != nil {
+ return nil, err
+ }
+ if findRes.Err() != nil {
+ return nil, findRes.Err()
+ }
+
+ for findRes.Next(dr.ctx) {
+ var service Service
+ err = findRes.Decode(&service)
+ if err != nil {
+ return nil, err
+ }
+ if service.ServiceInfo != nil {
+ return service.ServiceInfo, nil
+ }
+ }
+ return nil, nil
+}
+
+func (dr *DependencyRelation) getConsumerOfDependAllServices()
([]*pb.MicroServiceKey, error) {
+ providerService := pb.MicroServiceToKey(dr.domainProject, dr.provider)
+ providerService.ServiceName = "*"
+ filter := GenerateProviderDependencyRuleKey(dr.domainProject,
dr.provider.ServiceId, providerService)
+ findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionDep,
filter)
+ if err != nil {
+ return nil, err
+ }
+ if findRes.Err() != nil {
+ return nil, findRes.Err()
+ }
+
+ var msKeys []*pb.MicroServiceKey
+ for findRes.Next(dr.ctx) {
+ var dep *Dependency
+ err = findRes.Decode(&dep)
+ if err != nil {
+ return nil, err
+ }
+ msKeys = append(msKeys, dep.DependencyInfo.Consumer)
+ }
+ return msKeys, nil
+}
+
+func (dr *DependencyRelation) getProviderKeys() ([]*pb.MicroServiceKey, error)
{
+ if dr.consumer == nil {
+ return nil, ErrInvalidConsumer
+ }
+ consumerMicroServiceKey := pb.MicroServiceToKey(dr.domainProject,
dr.consumer)
+ filter := GenerateConsumerDependencyRuleKey(dr.domainProject,
dr.consumer.ServiceId, consumerMicroServiceKey)
+ findRes, err := client.GetMongoClient().Find(dr.ctx, CollectionDep,
filter)
+ if err != nil {
+ return nil, err
+ }
+ if findRes.Err() != nil {
+ return nil, findRes.Err()
+ }
+ var dep *Dependency
+ for findRes.Next(dr.ctx) {
+ err = findRes.Decode(&dep)
+ if err != nil {
+ return nil, err
+ }
+ if dep != nil {
+ break
+ }
+ }
+ if dep != nil {
+ return dep.DependencyInfo.Providers, nil
+ }
+ return nil, nil
+}
+
+func (dr *DependencyRelation) parseDependencyRule(dependencyRule
*pb.MicroServiceKey) (serviceIDs []string, err error) {
+ switch {
+ case dependencyRule.ServiceName == "*":
+ log.Info(fmt.Sprintf("service[%s/%s/%s/%s] rely all service",
+ dr.consumer.Environment, dr.consumer.AppId,
dr.consumer.ServiceName, dr.consumer.Version))
+ filter, err := MicroServiceKeyFilter(dependencyRule)
+ if err != nil {
+ log.Error("get serivce failed", err)
+ return nil, err
+ }
+ findRes, err := client.GetMongoClient().Find(dr.ctx,
CollectionService, filter)
+ if err != nil {
+ return nil, err
+ }
+ if findRes.Err() != nil {
+ return nil, findRes.Err()
+ }
+ for findRes.Next(dr.ctx) {
+ var service Service
+ err = findRes.Decode(&service)
+ if err != nil {
+ return nil, err
+ }
+ serviceIDs = append(serviceIDs,
service.ServiceInfo.ServiceId)
+ }
+ default:
+ serviceIDs, _, err = FindServiceIds(dr.ctx,
dependencyRule.Version, dependencyRule)
+ }
+ return
+}
+
+func (dr *DependencyRelation) GetDependencyConsumerIds() ([]string, error) {
+ consumerDependAllList, err := dr.GetDependencyConsumersOfProvider()
+ if err != nil {
+ return nil, err
+ }
+ consumerIDs := make([]string, 0, len(consumerDependAllList))
+ for _, consumer := range consumerDependAllList {
+ consumerID, err := GetServiceID(dr.ctx, consumer)
+ if err != nil {
+ log.Error(fmt.Sprintf("get consumer[%s/%s/%s/%s]
failed",
+ consumer.Environment, consumer.AppId,
consumer.ServiceName, consumer.Version), err)
+ return nil, err
+ }
+ if len(consumerID) == 0 {
+ log.Warn(fmt.Sprintf("get consumer[%s/%s/%s/%s] not
exist",
+ consumer.Environment, consumer.AppId,
consumer.ServiceName, consumer.Version))
+ continue
+ }
+ consumerIDs = append(consumerIDs, consumerID)
+ }
+ return consumerIDs, nil
+}
+
+func MicroServiceKeyFilter(key *pb.MicroServiceKey) (bson.M, error) {
+ tenant := strings.Split(key.Tenant, "/")
+ if len(tenant) != 2 {
+ return nil, ErrInvalidDomainProject
+ }
+ return bson.M{
+ ColumnDomain: tenant[0],
+ ColumnProject: tenant[1],
+ StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):
key.Environment,
+ StringBuilder([]string{ColumnServiceInfo, ColumnAppID}):
key.AppId,
+ StringBuilder([]string{ColumnServiceInfo, ColumnAlias}):
key.Alias,
+ StringBuilder([]string{ColumnServiceInfo, ColumnVersion}):
key.Version}, nil
+}
+
+func FindServiceIds(ctx context.Context, versionRule string, key
*pb.MicroServiceKey) (serviceIDs []string, b bool, err error) {
+ match, err := ParseVersionRule(ctx, versionRule, key)
+ if err != nil {
+ return nil, false, ErrInvalidDomainProject
+ }
+ if match == nil {
+ tenant := strings.Split(key.Tenant, "/")
+ if len(tenant) != 2 {
+ return nil, false, ErrInvalidDomainProject
+ }
+ filter := bson.M{
+ ColumnDomain: tenant[0],
+ ColumnProject: tenant[1],
+ StringBuilder([]string{ColumnServiceInfo, ColumnEnv}):
key.Environment,
+ StringBuilder([]string{ColumnServiceInfo,
ColumnVersion}): versionRule,
+ StringBuilder([]string{ColumnServiceInfo,
ColumnAppID}): key.AppId,
+ StringBuilder([]string{ColumnServiceInfo,
ColumnServiceName}): key.ServiceName,
+ StringBuilder([]string{ColumnServiceInfo,
ColumnAlias}): key.Alias}
+ findRes, err := client.GetMongoClient().Find(ctx,
CollectionService, filter)
+ if err != nil {
+ return nil, false, nil
+ }
+ if findRes.Err() != nil {
+ return nil, false, findRes.Err()
+ }
+ for findRes.Next(ctx) {
+ var service Service
+ err = findRes.Decode(&service)
+ if err != nil {
+ return nil, false, err
+ }
+ serviceIDs = append(serviceIDs,
service.ServiceInfo.ServiceId)
+ }
+ return serviceIDs, false, nil
+ }
+ return match, false, nil
+}
+
+func ParseVersionRule(ctx context.Context, versionRule string, key
*pb.MicroServiceKey) ([]string, error) {
+ tenant := strings.Split(key.Tenant, "/")
+ if len(tenant) != 2 {
+ return nil, ErrInvalidDomainProject
+ }
+ if len(versionRule) == 0 {
+ return nil, nil
+ }
+
+ rangeIdx := strings.Index(versionRule, "-")
+ switch {
+ case versionRule == "latest":
+ filter := bson.M{
+ ColumnDomain: tenant[0],
+ ColumnProject: tenant[1]}
+ return GetFilterVersionServiceLatest(ctx, filter)
+ case versionRule[len(versionRule)-1:] == "+":
+ start := versionRule[:len(versionRule)-1]
+ filter := bson.M{
+ ColumnDomain: tenant[0],
+ ColumnProject: tenant[1],
+ StringBuilder([]string{ColumnServiceInfo,
ColumnVersion}): bson.M{"$gte": start}}
+ return GetFilterVersionService(ctx, filter)
+ case rangeIdx > 0:
+ start := versionRule[:rangeIdx]
+ end := versionRule[rangeIdx+1:]
+ filter := bson.M{
+ ColumnDomain: tenant[0],
+ ColumnProject: tenant[1],
+ StringBuilder([]string{ColumnServiceInfo,
ColumnVersion}): bson.M{"$gte": start, "$lte": end}}
+ return GetFilterVersionService(ctx, filter)
+ default:
+ return nil, nil
+ }
+}
+
+func GetFilterVersionService(ctx context.Context, m bson.M) (serviceIDs
[]string, err error) {
+ findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m)
+ if err != nil {
+ return nil, err
+ }
+ if findRes.Err() != nil {
+ return nil, findRes.Err()
+ }
+ for findRes.Next(ctx) {
+ var service Service
+ err = findRes.Decode(&service)
+ if err != nil {
+ return nil, err
+ }
+ serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
+ }
+ return
+}
+
+func GetFilterVersionServiceLatest(ctx context.Context, m bson.M) (serviceIDs
[]string, err error) {
+ findRes, err := client.GetMongoClient().Find(ctx, CollectionService, m,
+ &options.FindOptions{
+ Sort: bson.M{StringBuilder([]string{ColumnServiceInfo,
ColumnVersion}): -1}})
+ if err != nil {
+ return nil, err
+ }
+ if findRes.Err() != nil {
+ return nil, findRes.Err()
+ }
+ for findRes.Next(ctx) {
+ var service Service
+ err = findRes.Decode(&service)
+ if err != nil {
+ return nil, err
+ }
+ serviceIDs = append(serviceIDs, service.ServiceInfo.ServiceId)
+ if serviceIDs != nil {
+ return serviceIDs, nil
+ }
+ }
+ return
+}
+
+func WithSameDomainProject() DependencyRelationFilterOption {
+ return func(opt DependencyRelationFilterOpt)
DependencyRelationFilterOpt {
+ opt.SameDomainProject = true
+ return opt
+ }
+}
+func WithoutSelfDependency() DependencyRelationFilterOption {
+ return func(opt DependencyRelationFilterOpt)
DependencyRelationFilterOpt {
+ opt.NonSelf = true
+ return opt
+ }
+}
+
+func ToDependencyFilterOptions(in *pb.GetDependenciesRequest) (opts
[]DependencyRelationFilterOption) {
+ if in.SameDomain {
+ opts = append(opts, WithSameDomainProject())
+ }
+ if in.NoSelf {
+ opts = append(opts, WithoutSelfDependency())
+ }
+ return opts
+}
+
+func ToDependencyRelationFilterOpt(opts ...DependencyRelationFilterOption) (op
DependencyRelationFilterOpt) {
+ for _, opt := range opts {
+ op = opt(op)
+ }
+ return
+}
+
+func GenerateConsumerDependencyRuleKey(domainProject string, serviceID string,
in *pb.MicroServiceKey) bson.M {
+ return GenerateServiceDependencyRuleKey(domainProject, serviceID, in)
+}
+
+func GenerateProviderDependencyRuleKey(domainProject string, serviceID string,
in *pb.MicroServiceKey) bson.M {
+ return GenerateServiceDependencyRuleKey(domainProject, serviceID, in)
+}
+
+func GenerateServiceDependencyRuleKey(domainProject string, serviceID string,
in *pb.MicroServiceKey) bson.M {
+ if in == nil {
+ return bson.M{
+ ColumnConsumerID: serviceID,
+ StringBuilder([]string{ColumnDependencyInfo,
ColumnConsumer, ColumnTenant}): domainProject}
+ }
+ if in.ServiceName == "*" {
+ return bson.M{
+ ColumnConsumerID: serviceID,
+ StringBuilder([]string{ColumnDependencyInfo,
ColumnConsumer, ColumnTenant}): domainProject,
+ StringBuilder([]string{ColumnDependencyInfo,
ColumnConsumer, ColumnEnv}): in.Environment,
+ StringBuilder([]string{ColumnDependencyInfo,
ColumnConsumer, ColumnServiceName}): in.ServiceName}
+ }
+ return bson.M{
+ ColumnConsumerID: serviceID,
+ StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer,
ColumnTenant}): domainProject,
+ StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer,
ColumnEnv}): in.Environment,
+ StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer,
ColumnAppID}): in.AppId,
+ StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer,
ColumnVersion}): in.Version,
+ StringBuilder([]string{ColumnDependencyInfo, ColumnConsumer,
ColumnServiceName}): in.ServiceName}
+}
diff --git a/datasource/mongo/ms.go b/datasource/mongo/ms.go
index 46811ee..106cfca 100644
--- a/datasource/mongo/ms.go
+++ b/datasource/mongo/ms.go
@@ -1470,15 +1470,17 @@ func (ds *DataSource) GetInstance(ctx context.Context,
request *discovery.GetOne
fmt.Sprintf("Provider[%s] does not exist.",
request.ProviderServiceId)),
}, nil
}
- findFlag := fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find
provider[%s][%s/%s/%s/%s] instance[%s]",
- request.ConsumerServiceId, service.ServiceInfo.Environment,
service.ServiceInfo.AppId, service.ServiceInfo.ServiceName,
service.ServiceInfo.Version,
- provider.ServiceInfo.ServiceId,
provider.ServiceInfo.Environment, provider.ServiceInfo.AppId,
provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version,
- request.ProviderInstanceId)
+ findFlag := func() string {
+ return fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find
provider[%s][%s/%s/%s/%s] instance[%s]",
+ request.ConsumerServiceId,
service.ServiceInfo.Environment, service.ServiceInfo.AppId,
service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
+ provider.ServiceInfo.ServiceId,
provider.ServiceInfo.Environment, provider.ServiceInfo.AppId,
provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version,
+ request.ProviderInstanceId)
+ }
domainProject := util.ParseDomainProject(ctx)
services, err := findServices(ctx,
discovery.MicroServiceToKey(domainProject, provider.ServiceInfo))
if err != nil {
- log.Error(fmt.Sprintf("get instance failed %s", findFlag), err)
+ log.Error(fmt.Sprintf("get instance failed %s", findFlag()),
err)
return &discovery.GetOneInstanceResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
}, err
@@ -1487,7 +1489,7 @@ func (ds *DataSource) GetInstance(ctx context.Context,
request *discovery.GetOne
serviceIDs = filterServiceIDs(ctx, request.ConsumerServiceId,
request.Tags, services)
}
if services == nil || len(serviceIDs) == 0 {
- mes := fmt.Errorf("%s failed, provider does not exist",
findFlag)
+ mes := fmt.Errorf("%s failed, provider does not exist",
findFlag())
log.Error("get instance failed", mes)
return &discovery.GetOneInstanceResponse{
Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -1495,7 +1497,7 @@ func (ds *DataSource) GetInstance(ctx context.Context,
request *discovery.GetOne
}
instances, err := instancesFilter(ctx, serviceIDs)
if len(instances) == 0 {
- mes := fmt.Errorf("%s failed, provider instance does not
exist", findFlag)
+ mes := fmt.Errorf("%s failed, provider instance does not
exist", findFlag())
log.Error("get instance failed", err)
return &discovery.GetOneInstanceResponse{
Response:
discovery.CreateResponse(discovery.ErrInstanceNotExists, mes.Error()),
@@ -1551,13 +1553,15 @@ func (ds *DataSource) GetInstances(ctx context.Context,
request *discovery.GetIn
}, nil
}
- findFlag := fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find
provider[%s][%s/%s/%s/%s] instances",
- request.ConsumerServiceId, service.ServiceInfo.Environment,
service.ServiceInfo.AppId, service.ServiceInfo.ServiceName,
service.ServiceInfo.Version,
- provider.ServiceInfo.ServiceId,
provider.ServiceInfo.Environment, provider.ServiceInfo.AppId,
provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version)
+ findFlag := func() string {
+ return fmt.Sprintf("consumer[%s][%s/%s/%s/%s] find
provider[%s][%s/%s/%s/%s] instances",
+ request.ConsumerServiceId,
service.ServiceInfo.Environment, service.ServiceInfo.AppId,
service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
+ provider.ServiceInfo.ServiceId,
provider.ServiceInfo.Environment, provider.ServiceInfo.AppId,
provider.ServiceInfo.ServiceName, provider.ServiceInfo.Version)
+ }
services, err := findServices(ctx,
discovery.MicroServiceToKey(domainProject, provider.ServiceInfo))
if err != nil {
- log.Error(fmt.Sprintf("get instances failed %s", findFlag), err)
+ log.Error(fmt.Sprintf("get instances failed %s", findFlag()),
err)
return &discovery.GetInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
}, err
@@ -1566,7 +1570,7 @@ func (ds *DataSource) GetInstances(ctx context.Context,
request *discovery.GetIn
serviceIDs = filterServiceIDs(ctx, request.ConsumerServiceId,
request.Tags, services)
}
if services == nil || len(serviceIDs) == 0 {
- mes := fmt.Errorf("%s failed, provider does not exist",
findFlag)
+ mes := fmt.Errorf("%s failed, provider does not exist",
findFlag())
log.Error("get instances failed", mes)
return &discovery.GetInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -1574,7 +1578,7 @@ func (ds *DataSource) GetInstances(ctx context.Context,
request *discovery.GetIn
}
instances, err := instancesFilter(ctx, serviceIDs)
if err != nil {
- log.Error(fmt.Sprintf("get instances failed %s", findFlag), err)
+ log.Error(fmt.Sprintf("get instances failed %s", findFlag()),
err)
return &discovery.GetInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
}, err
@@ -1924,16 +1928,18 @@ func (ds *DataSource) findSharedServiceInstance(ctx
context.Context, request *di
var err error
// it means the shared micro-services must be the same env with SC.
provider.Environment = apt.Service.Environment
- findFlag := fmt.Sprintf("find shared provider[%s/%s/%s/%s]",
provider.Environment, provider.AppId, provider.ServiceName, provider.Version)
+ findFlag := func() string {
+ return fmt.Sprintf("find shared provider[%s/%s/%s/%s]",
provider.Environment, provider.AppId, provider.ServiceName, provider.Version)
+ }
services, err := findServices(ctx, provider)
if err != nil {
- log.Error(fmt.Sprintf("find shared service instance failed %s",
findFlag), err)
+ log.Error(fmt.Sprintf("find shared service instance failed %s",
findFlag()), err)
return &discovery.FindInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
}, err
}
if services == nil {
- mes := fmt.Errorf("%s failed, provider does not exist",
findFlag)
+ mes := fmt.Errorf("%s failed, provider does not exist",
findFlag())
log.Error("find shared service instance failed", mes)
return &discovery.FindInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -1948,7 +1954,7 @@ func (ds *DataSource) findSharedServiceInstance(ctx
context.Context, request *di
}
instances, err := instancesFilter(ctx, serviceIDs)
if err != nil {
- log.Error(fmt.Sprintf("find shared service instance failed %s",
findFlag), err)
+ log.Error(fmt.Sprintf("find shared service instance failed %s",
findFlag()), err)
return &discovery.FindInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
}, err
@@ -1989,18 +1995,20 @@ func (ds *DataSource) findInstance(ctx context.Context,
request *discovery.FindI
ctx = util.SetTargetDomainProject(ctx, util.ParseDomain(ctx),
util.ParseProject(ctx))
provider.Tenant = util.ParseTargetDomainProject(ctx)
- findFlag := fmt.Sprintf("Consumer[%s][%s/%s/%s/%s] find
provider[%s/%s/%s/%s]",
- request.ConsumerServiceId, service.ServiceInfo.Environment,
service.ServiceInfo.AppId, service.ServiceInfo.ServiceName,
service.ServiceInfo.Version,
- provider.Environment, provider.AppId, provider.ServiceName,
provider.Version)
+ findFlag := func() string {
+ return fmt.Sprintf("Consumer[%s][%s/%s/%s/%s] find
provider[%s/%s/%s/%s]",
+ request.ConsumerServiceId,
service.ServiceInfo.Environment, service.ServiceInfo.AppId,
service.ServiceInfo.ServiceName, service.ServiceInfo.Version,
+ provider.Environment, provider.AppId,
provider.ServiceName, provider.Version)
+ }
services, err := findServices(ctx, provider)
if err != nil {
- log.Error(fmt.Sprintf("find instance failed %s", findFlag), err)
+ log.Error(fmt.Sprintf("find instance failed %s", findFlag()),
err)
return &discovery.FindInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
}, err
}
if services == nil {
- mes := fmt.Errorf("%s failed, provider does not exist",
findFlag)
+ mes := fmt.Errorf("%s failed, provider does not exist",
findFlag())
log.Error("find instance failed", mes)
return &discovery.FindInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
@@ -2015,7 +2023,7 @@ func (ds *DataSource) findInstance(ctx context.Context,
request *discovery.FindI
}
instances, err := instancesFilter(ctx, serviceIDs)
if err != nil {
- log.Error(fmt.Sprintf("find instance failed %s", findFlag), err)
+ log.Error(fmt.Sprintf("find instance failed %s", findFlag()),
err)
return &discovery.FindInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
}, err
@@ -2030,14 +2038,14 @@ func (ds *DataSource) findInstance(ctx context.Context,
request *discovery.FindI
if provider != nil {
err = AddServiceVersionRule(ctx, domainProject,
service.ServiceInfo, provider)
} else {
- mes := fmt.Errorf("%s failed, provider does not exist",
findFlag)
+ mes := fmt.Errorf("%s failed, provider does not exist",
findFlag())
log.Error("add service version rule failed", mes)
return &discovery.FindInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrServiceNotExists, mes.Error()),
}, nil
}
if err != nil {
- log.Error(fmt.Sprintf("add service version rule failed
%s", findFlag), err)
+ log.Error(fmt.Sprintf("add service version rule failed
%s", findFlag()), err)
return &discovery.FindInstancesResponse{
Response:
discovery.CreateResponse(discovery.ErrInternal, err.Error()),
}, err