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 4fb55ad9 Feature: add properties filter in ListServiceDetail API
(#1324)
4fb55ad9 is described below
commit 4fb55ad9b788530e93812f71eaec969228b481c4
Author: little-cui <[email protected]>
AuthorDate: Sat Aug 20 09:31:19 2022 +0800
Feature: add properties filter in ListServiceDetail API (#1324)
* [fix]govern properties is nil
* Feature: add properties filter in ListServiceDetail API
* Feature: add properties filter in ListServiceDetail API
---
datasource/etcd/etcd.go | 3 +-
datasource/etcd/ms.go | 93 +----------
datasource/etcd/util.go | 100 ------------
datasource/mongo/mongo.go | 3 +-
datasource/mongo/ms.go | 148 +----------------
datasource/ms.go | 3 +-
datasource/ms_util.go | 29 ----
datasource/ms_util_test.go | 62 -------
datasource/options.go | 3 +-
datasource/service_test.go | 146 -----------------
server/resource/govern/govern_resource.go | 18 +++
server/resource/govern/govern_resource_test.go | 90 ++++++++++-
server/server.go | 5 +-
server/service/disco/retire_test.go | 3 +-
server/service/govern/view.go | 216 ++++++++++++++++++++++++-
server/service/govern/view_test.go | 105 ++++++++++--
16 files changed, 428 insertions(+), 599 deletions(-)
diff --git a/datasource/etcd/etcd.go b/datasource/etcd/etcd.go
index 4d66c5d1..684beaed 100644
--- a/datasource/etcd/etcd.go
+++ b/datasource/etcd/etcd.go
@@ -94,8 +94,7 @@ func NewDataSource(opts datasource.Options)
(datasource.DataSource, error) {
return nil, err
}
inst.metadataManager = &MetadataManager{
- InstanceTTL: opts.InstanceTTL,
- InstanceProperties: opts.InstanceProperties,
+ InstanceTTL: opts.InstanceTTL,
}
inst.sysManager = &SysManager{}
inst.depManager = &DepManager{}
diff --git a/datasource/etcd/ms.go b/datasource/etcd/ms.go
index 4509a85e..66cc4908 100644
--- a/datasource/etcd/ms.go
+++ b/datasource/etcd/ms.go
@@ -49,8 +49,7 @@ import (
type MetadataManager struct {
// InstanceTTL options
- InstanceTTL int64
- InstanceProperties map[string]string
+ InstanceTTL int64
}
// RegisterService implement:
@@ -186,92 +185,6 @@ func (ds *MetadataManager) GetService(ctx context.Context,
request *pb.GetServic
return singleService, nil
}
-func (ds *MetadataManager) ListServiceDetail(ctx context.Context, request
*pb.GetServicesInfoRequest) (
- *pb.GetServicesInfoResponse, error) {
- ctx = util.WithCacheOnly(ctx)
-
- optionMap := make(map[string]struct{}, len(request.Options))
- for _, opt := range request.Options {
- optionMap[opt] = struct{}{}
- }
-
- options := make([]string, 0, len(optionMap))
- if _, ok := optionMap["all"]; ok {
- optionMap["statistics"] = struct{}{}
- options = []string{"tags", "instances", "schemas",
"dependencies"}
- } else {
- for opt := range optionMap {
- options = append(options, opt)
- }
- }
-
- var st *pb.Statistics
- if _, ok := optionMap["statistics"]; ok {
- var err error
- st, err = statistics(ctx, request.WithShared)
- if err != nil {
- return nil, pb.NewError(pb.ErrInternal, err.Error())
- }
- if len(optionMap) == 1 {
- return &pb.GetServicesInfoResponse{
- Statistics: st,
- }, nil
- }
- }
-
- //获取所有服务
- services, err := eutil.GetAllServiceUtil(ctx)
- if err != nil {
- log.Error("get all services by domain failed", err)
- return nil, pb.NewError(pb.ErrInternal, err.Error())
- }
-
- allServiceDetails := make([]*pb.ServiceDetail, 0, len(services))
- domainProject := util.ParseDomainProject(ctx)
- for _, service := range services {
- if !ds.filterServices(domainProject, request, service) {
- continue
- }
-
- serviceDetail, err := getServiceDetailUtil(ctx,
ServiceDetailOpt{
- domainProject: domainProject,
- service: service,
- countOnly: request.CountOnly,
- options: options,
- })
- if err != nil {
- return nil, pb.NewError(pb.ErrInternal, err.Error())
- }
- serviceDetail.MicroService = service
- tmpServiceDetail, err :=
datasource.NewServiceOverview(serviceDetail, ds.InstanceProperties)
- if err != nil {
- return nil, err
- }
- allServiceDetails = append(allServiceDetails, tmpServiceDetail)
- }
-
- return &pb.GetServicesInfoResponse{
- AllServicesDetail: allServiceDetails,
- Statistics: st,
- }, nil
-}
-
-func (ds *MetadataManager) filterServices(domainProject string, request
*pb.GetServicesInfoRequest, service *pb.MicroService) bool {
- if !request.WithShared &&
datasource.IsGlobal(pb.MicroServiceToKey(domainProject, service)) {
- return false
- }
- if len(request.Environment) > 0 && request.Environment !=
service.Environment {
- return false
- }
- if len(request.AppId) > 0 && request.AppId != service.AppId {
- return false
- }
- if len(request.ServiceName) > 0 && request.ServiceName !=
service.ServiceName {
- return false
- }
- return true
-}
-
func (ds *MetadataManager) GetOverview(ctx context.Context, request
*pb.GetServicesRequest) (
*pb.Statistics, error) {
ctx = util.WithCacheOnly(ctx)
@@ -1652,3 +1565,7 @@ func (ds *MetadataManager) UnregisterService(ctx
context.Context, request *pb.De
log.Info(fmt.Sprintf("%s micro-service[%s] successfully, operator: %s",
title, serviceID, remoteIP))
return nil
}
+
+func (ds *MetadataManager) Statistics(ctx context.Context, withShared bool)
(*pb.Statistics, error) {
+ return statistics(ctx, withShared)
+}
diff --git a/datasource/etcd/util.go b/datasource/etcd/util.go
index 6aca94e1..d41215f4 100644
--- a/datasource/etcd/util.go
+++ b/datasource/etcd/util.go
@@ -36,13 +36,6 @@ import (
"github.com/apache/servicecomb-service-center/pkg/util"
)
-type ServiceDetailOpt struct {
- domainProject string
- service *pb.MicroService
- countOnly bool
- options []string
-}
-
// schema
func getSchemaSummary(ctx context.Context, domainProject string, serviceID
string, schemaID string) (string, error) {
key := path.GenerateServiceSchemaSummaryKey(domainProject, serviceID,
schemaID)
@@ -205,99 +198,6 @@ func revokeInstance(ctx context.Context, domainProject
string, serviceID string,
return nil
}
-func getServiceDetailUtil(ctx context.Context, serviceDetailOpt
ServiceDetailOpt) (*pb.ServiceDetail, error) {
- serviceID := serviceDetailOpt.service.ServiceId
- options := serviceDetailOpt.options
- domainProject := serviceDetailOpt.domainProject
- serviceDetail := new(pb.ServiceDetail)
- if serviceDetailOpt.countOnly {
- serviceDetail.Statics = new(pb.Statistics)
- }
-
- for _, opt := range options {
- expr := opt
- switch expr {
- case "tags":
- tags, err := serviceUtil.GetTagsUtils(ctx,
domainProject, serviceID)
- if err != nil {
- log.Error(fmt.Sprintf("get service[%s]'s all
tags failed", serviceID), err)
- return nil, err
- }
- serviceDetail.Tags = tags
- case "instances":
- if serviceDetailOpt.countOnly {
- instanceCount, err :=
serviceUtil.GetInstanceCountOfOneService(ctx, domainProject, serviceID)
- if err != nil {
- log.Error(fmt.Sprintf("get number of
service[%s]'s instances failed", serviceID), err)
- return nil, err
- }
- serviceDetail.Statics.Instances =
&pb.StInstance{
- Count: instanceCount}
- continue
- }
- instances, err :=
serviceUtil.GetAllInstancesOfOneService(ctx, domainProject, 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 := getSchemaInfoUtil(ctx, domainProject,
serviceID)
- if err != nil {
- log.Error(fmt.Sprintf("get service[%s]'s all
schemas failed", serviceID), err)
- return nil, err
- }
- serviceDetail.SchemaInfos = schemas
- case "dependencies":
- service := serviceDetailOpt.service
- consumers, err := serviceUtil.GetConsumers(ctx,
domainProject, service,
- serviceUtil.WithoutSelfDependency(),
- serviceUtil.WithSameDomainProject())
- if err != nil {
- log.Error(fmt.Sprintf("get
service[%s][%s/%s/%s/%s]'s all consumers failed",
- service.ServiceId, service.Environment,
service.AppId, service.ServiceName, service.Version), err)
- return nil, err
- }
- providers, err := serviceUtil.GetProviders(ctx,
domainProject, service,
- serviceUtil.WithoutSelfDependency(),
- serviceUtil.WithSameDomainProject())
- if err != nil {
- log.Error(fmt.Sprintf("get
service[%s][%s/%s/%s/%s]'s all providers failed",
- service.ServiceId, service.Environment,
service.AppId, service.ServiceName, service.Version), err)
- return nil, err
- }
-
- serviceDetail.Consumers = consumers
- serviceDetail.Providers = providers
- case "":
- continue
- default:
- log.Error(fmt.Sprintf("request option[%s] is invalid",
opt), nil)
- }
- }
- return serviceDetail, nil
-}
-
-func getSchemaInfoUtil(ctx context.Context, domainProject string, serviceID
string) ([]*pb.Schema, error) {
- key := path.GenerateServiceSchemaKey(domainProject, serviceID, "")
-
- resp, err := sd.Schema().Search(ctx,
- etcdadpt.WithStrKey(key),
- etcdadpt.WithPrefix())
- if err != nil {
- log.Error(fmt.Sprintf("get service[%s]'s schemas failed",
serviceID), err)
- return make([]*pb.Schema, 0), err
- }
- schemas := make([]*pb.Schema, 0, len(resp.Kvs))
- for _, kv := range resp.Kvs {
- schemaInfo := &pb.Schema{}
- schemaInfo.Schema =
util.BytesToStringWithNoCopy(kv.Value.([]byte))
- schemaInfo.SchemaId =
util.BytesToStringWithNoCopy(kv.Key[len(key):])
- schemas = append(schemas, schemaInfo)
- }
- return schemas, nil
-}
-
func statistics(ctx context.Context, withShared bool) (*pb.Statistics, error) {
result := &pb.Statistics{
Services: &pb.StService{},
diff --git a/datasource/mongo/mongo.go b/datasource/mongo/mongo.go
index d6c2a2c2..08d850d4 100644
--- a/datasource/mongo/mongo.go
+++ b/datasource/mongo/mongo.go
@@ -82,8 +82,7 @@ func NewDataSource(opts datasource.Options)
(datasource.DataSource, error) {
inst.depManager = &DepManager{}
inst.sysManager = &SysManager{}
inst.metadataManager = &MetadataManager{
- InstanceTTL: opts.InstanceTTL,
- InstanceProperties: opts.InstanceProperties,
+ InstanceTTL: opts.InstanceTTL,
}
inst.metricsManager = &MetricsManager{}
inst.syncManager = &SyncManager{}
diff --git a/datasource/mongo/ms.go b/datasource/mongo/ms.go
index 58f0cd3c..3fed2580 100644
--- a/datasource/mongo/ms.go
+++ b/datasource/mongo/ms.go
@@ -57,8 +57,7 @@ const baseTen = 10
type MetadataManager struct {
// InstanceTTL options
- InstanceTTL int64
- InstanceProperties map[string]string
+ InstanceTTL int64
}
func (ds *MetadataManager) RegisterService(ctx context.Context, request
*discovery.CreateServiceRequest) (*discovery.CreateServiceResponse, error) {
@@ -392,80 +391,6 @@ func updateServiceTxn(ctx context.Context, request
*discovery.UpdateServiceProps
})
}
-func (ds *MetadataManager) ListServiceDetail(ctx context.Context, request
*discovery.GetServicesInfoRequest) (*discovery.GetServicesInfoResponse, error) {
- optionMap := make(map[string]struct{}, len(request.Options))
- for _, opt := range request.Options {
- optionMap[opt] = struct{}{}
- }
-
- options := make([]string, 0, len(optionMap))
- if _, ok := optionMap["all"]; ok {
- optionMap["statistics"] = struct{}{}
- options = []string{"tags", "instances", "schemas",
"dependencies"}
- } else {
- for opt := range optionMap {
- options = append(options, opt)
- }
- }
- var st *discovery.Statistics
- if _, ok := optionMap["statistics"]; ok {
- var err error
- st, err = statistics(ctx, request.WithShared)
- if err != nil {
- return nil, discovery.NewError(discovery.ErrInternal,
err.Error())
- }
- if len(optionMap) == 1 {
- return &discovery.GetServicesInfoResponse{
- Statistics: st,
- }, nil
- }
- }
- filters := ds.filterServices(ctx, request)
- services, err := dao.GetServices(ctx, filters)
- if err != nil {
- log.Error("get all services by domain failed", err)
- return nil, discovery.NewError(discovery.ErrInternal,
err.Error())
- }
- allServiceDetails := make([]*discovery.ServiceDetail, 0, len(services))
- domainProject := util.ParseDomainProject(ctx)
- for _, mgSvc := range services {
- if !request.WithShared &&
datasource.IsGlobal(discovery.MicroServiceToKey(domainProject, mgSvc.Service)) {
- continue
- }
-
- serviceDetail, err := getServiceDetailUtil(ctx, mgSvc,
request.CountOnly, options)
- if err != nil {
- return nil, discovery.NewError(discovery.ErrInternal,
err.Error())
- }
- serviceDetail.MicroService = mgSvc.Service
- tmpServiceDetail, err :=
datasource.NewServiceOverview(serviceDetail, ds.InstanceProperties)
- if err != nil {
- return nil, err
- }
- allServiceDetails = append(allServiceDetails, tmpServiceDetail)
- }
-
- return &discovery.GetServicesInfoResponse{
- AllServicesDetail: allServiceDetails,
- Statistics: st,
- }, nil
-}
-
-func (ds *MetadataManager) filterServices(ctx context.Context, request
*discovery.GetServicesInfoRequest) bson.M {
- var opts []func(filter bson.M)
-
- if len(request.Environment) > 0 {
- opts = append(opts, mutil.ServiceEnv(request.Environment))
- }
- if len(request.AppId) > 0 {
- opts = append(opts, mutil.ServiceAppID(request.AppId))
- }
- if len(request.ServiceName) > 0 {
- opts = append(opts,
mutil.ServiceServiceName(request.ServiceName))
- }
- return mutil.NewBasicFilter(ctx, opts...)
-}
-
func (ds *MetadataManager) GetOverview(ctx context.Context, request
*discovery.GetServicesRequest) (
*discovery.Statistics, error) {
ctx = util.WithCacheOnly(ctx)
@@ -855,73 +780,6 @@ func (ds *MetadataManager) modifySchema(ctx
context.Context, serviceID string, s
return nil
}
-func getServiceDetailUtil(ctx context.Context, mgs *model.Service, countOnly
bool, options []string) (*discovery.ServiceDetail, error) {
- serviceDetail := new(discovery.ServiceDetail)
- serviceID := mgs.Service.ServiceId
- domainProject := util.ParseDomainProject(ctx)
- domain := util.ParseDomain(ctx)
- project := util.ParseProject(ctx)
- if countOnly {
- serviceDetail.Statics = new(discovery.Statistics)
- }
- for _, opt := range options {
- expr := opt
- switch expr {
- case "tags":
- serviceDetail.Tags = mgs.Tags
- case "instances":
- if countOnly {
- instanceCount, err := CountInstance(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
- }
- filter := mutil.NewDomainProjectFilter(domain, project,
mutil.InstanceServiceID(serviceID))
- instances, err := dao.GetMicroServiceInstances(ctx,
filter)
- if err != nil {
- log.Error(fmt.Sprintf("get service[%s]'s all
instances failed", serviceID), err)
- return nil, err
- }
- serviceDetail.Instances = instances
- case "schemas":
- filter := mutil.NewDomainProjectFilter(domain, project,
mutil.ServiceID(serviceID))
- schemas, err := dao.GetSchemas(ctx, filter)
- if err != nil {
- log.Error(fmt.Sprintf("get service %s's all
schemas failed", mgs.Service.ServiceId), err)
- return nil, err
- }
- serviceDetail.SchemaInfos = schemas
- case "dependencies":
- service := mgs.Service
- consumers, err := GetConsumers(ctx, domainProject,
service,
- WithoutSelfDependency(),
WithSameDomainProject())
- if err != nil {
- log.Error(fmt.Sprintf("get
service[%s][%s/%s/%s/%s]'s all consumers failed",
- service.ServiceId, service.Environment,
service.AppId, service.ServiceName, service.Version), err)
- }
- providers, err := GetProviders(ctx, domainProject,
service,
- WithoutSelfDependency(),
WithSameDomainProject())
- if err != nil {
- log.Error(fmt.Sprintf("get
service[%s][%s/%s/%s/%s]'s all providers failed",
- service.ServiceId, service.Environment,
service.AppId, service.ServiceName, service.Version), err)
- return nil, err
- }
- serviceDetail.Consumers = consumers
- serviceDetail.Providers = providers
- case "":
- continue
- default:
- log.Info(fmt.Sprintf("request option %s is invalid",
opt))
- }
- }
- return serviceDetail, nil
-}
-
// Instance management
func (ds *MetadataManager) RegisterInstance(ctx context.Context,
request *discovery.RegisterInstanceRequest)
(*discovery.RegisterInstanceResponse, error) {
@@ -1815,3 +1673,7 @@ func formatRevision(consumerServiceID string, instances
[]*discovery.MicroServic
s := fmt.Sprintf("%s.%x", consumerServiceID, sha1.Sum(data))
return fmt.Sprintf("%x", sha1.Sum(util.StringToBytesWithNoCopy(s))), nil
}
+
+func (ds *MetadataManager) Statistics(ctx context.Context, withShared bool)
(*discovery.Statistics, error) {
+ return statistics(ctx, withShared)
+}
diff --git a/datasource/ms.go b/datasource/ms.go
index 073a3dd5..52a6e29e 100644
--- a/datasource/ms.go
+++ b/datasource/ms.go
@@ -46,7 +46,6 @@ type MetadataManager interface {
ListService(ctx context.Context, request *pb.GetServicesRequest)
(*pb.GetServicesResponse, error)
GetService(ctx context.Context, request *pb.GetServiceRequest)
(*pb.MicroService, error)
- ListServiceDetail(ctx context.Context, request
*pb.GetServicesInfoRequest) (*pb.GetServicesInfoResponse, error)
GetOverview(ctx context.Context, request *pb.GetServicesRequest)
(*pb.Statistics, error)
ListApp(ctx context.Context, request *pb.GetAppsRequest)
(*pb.GetAppsResponse, error)
@@ -92,4 +91,6 @@ type MetadataManager interface {
// RetireService retire the 'RetirePlan.Reserve' latest versions for
each of service,
// delete other versions which doesn't register any instances.
RetireService(ctx context.Context, plan *RetirePlan) error
+
+ Statistics(ctx context.Context, withShared bool) (*pb.Statistics, error)
}
diff --git a/datasource/ms_util.go b/datasource/ms_util.go
index c948dc2a..54df3181 100644
--- a/datasource/ms_util.go
+++ b/datasource/ms_util.go
@@ -20,7 +20,6 @@ package datasource
import (
"github.com/apache/servicecomb-service-center/pkg/util"
"github.com/go-chassis/cari/discovery"
- "github.com/jinzhu/copier"
)
var GlobalServiceNames = make(map[string]struct{})
@@ -145,31 +144,3 @@ func RemoveGlobalServices(withShared bool, domainProject
string,
func IsDefaultDomainProject(domainProject string) bool {
return domainProject == RegistryDomainProject
}
-
-func NewServiceOverview(serviceDetail *discovery.ServiceDetail,
innerProperties map[string]string) (*discovery.ServiceDetail, error) {
- tmpServiceDetail := &discovery.ServiceDetail{}
- err := copier.CopyWithOption(tmpServiceDetail, serviceDetail,
copier.Option{DeepCopy: true})
- if err != nil {
- return nil, discovery.NewError(discovery.ErrInternal,
err.Error())
- }
- tmpServiceDetail.MicroService.Properties = nil
- tmpServiceDetail.MicroService.Schemas = nil
- instances := tmpServiceDetail.Instances
- for _, instance := range instances {
- instance.Properties =
removeCustomProperties(instance.Properties, innerProperties)
- }
- return tmpServiceDetail, nil
-}
-
-func removeCustomProperties(properties, innerProperties map[string]string)
map[string]string {
- if len(innerProperties) == 0 {
- return nil
- }
- props := make(map[string]string)
- for k, v := range properties {
- if _, ok := innerProperties[k]; ok {
- props[k] = v
- }
- }
- return props
-}
diff --git a/datasource/ms_util_test.go b/datasource/ms_util_test.go
index b4fd2a29..f89f3fe8 100644
--- a/datasource/ms_util_test.go
+++ b/datasource/ms_util_test.go
@@ -116,65 +116,3 @@ func hasGlobalService(services []*discovery.MicroService)
bool {
}
return false
}
-
-func TestNewServiceOverview(t *testing.T) {
- t.Run("no instances, should be ok", func(t *testing.T) {
- _, err :=
datasource.NewServiceOverview(&discovery.ServiceDetail{
- MicroService: &discovery.MicroService{},
- }, nil)
- assert.NoError(t, err)
-
- _, err = datasource.NewServiceOverview(&discovery.ServiceDetail{
- MicroService: &discovery.MicroService{},
- Instances: []*discovery.MicroServiceInstance{},
- }, nil)
- assert.NoError(t, err)
- })
-
- t.Run("has schema or service properties, should be ok", func(t
*testing.T) {
- overview, err :=
datasource.NewServiceOverview(&discovery.ServiceDetail{
- MicroService: &discovery.MicroService{
- Schemas: []string{"test"},
- Properties: map[string]string{"test": "A"},
- },
- }, nil)
- assert.NoError(t, err)
- assert.Empty(t, overview.MicroService.Schemas)
- assert.Empty(t, overview.MicroService.Properties)
- })
-
- t.Run("has instance properties, should be ok", func(t *testing.T) {
- overview, err :=
datasource.NewServiceOverview(&discovery.ServiceDetail{
- MicroService: &discovery.MicroService{},
- Instances: []*discovery.MicroServiceInstance{
- {
- Properties: map[string]string{"test":
"A"},
- },
- },
- }, nil)
- assert.NoError(t, err)
- assert.Empty(t, overview.Instances[0].Properties)
-
- overview, err =
datasource.NewServiceOverview(&discovery.ServiceDetail{
- MicroService: &discovery.MicroService{},
- Instances: []*discovery.MicroServiceInstance{
- {
- Properties: map[string]string{"test":
"A"},
- },
- },
- }, map[string]string{"inner": "B"})
- assert.NoError(t, err)
- assert.Empty(t, overview.Instances[0].Properties)
-
- overview, err =
datasource.NewServiceOverview(&discovery.ServiceDetail{
- MicroService: &discovery.MicroService{},
- Instances: []*discovery.MicroServiceInstance{
- {
- Properties: map[string]string{"test":
"A", "inner": "C"},
- },
- },
- }, map[string]string{"inner": "B"})
- assert.NoError(t, err)
- assert.Equal(t, "C", overview.Instances[0].Properties["inner"])
- })
-}
diff --git a/datasource/options.go b/datasource/options.go
index 9bce1a4a..f5295143 100644
--- a/datasource/options.go
+++ b/datasource/options.go
@@ -43,6 +43,5 @@ type Options struct {
EnableCache bool
// InstanceTTL: the default ttl of instance lease
- InstanceTTL int64
- InstanceProperties map[string]string
+ InstanceTTL int64
}
diff --git a/datasource/service_test.go b/datasource/service_test.go
index b736bfb2..5e373e21 100644
--- a/datasource/service_test.go
+++ b/datasource/service_test.go
@@ -571,152 +571,6 @@ func TestService_Delete(t *testing.T) {
})
}
-func TestService_Info(t *testing.T) {
- var (
- serviceID string
- instanceID string
- )
- ctx := getContext()
- defer datasource.GetMetadataManager().UnregisterService(ctx,
&pb.DeleteServiceRequest{ServiceId: serviceID, Force: true})
-
- t.Run("register a tested service & instance, should be passed", func(t
*testing.T) {
- resp, err :=
datasource.GetMetadataManager().RegisterService(ctx, &pb.CreateServiceRequest{
- Service: &pb.MicroService{
- ServiceName: "TestServic1",
- AppId: "default",
- Version: "1.0.0",
- Level: "FRONT",
- Status: "UP",
- },
- })
- assert.NoError(t, err)
- serviceID = resp.ServiceId
-
- instance := &pb.MicroServiceInstance{
- ServiceId: serviceID,
- Endpoints: []string{
- "rest://[::]:301000/",
- },
- HostName: "delete-host-ms",
- Status: pb.MSI_UP,
- }
- respInstance, err :=
datasource.GetMetadataManager().RegisterInstance(ctx,
&pb.RegisterInstanceRequest{
- Instance: instance,
- })
- assert.NoError(t, err)
- instanceID = respInstance.InstanceId
- })
-
- t.Run("get tested service info, should be passed", func(t *testing.T) {
- resp, err :=
datasource.GetMetadataManager().ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
- Options: []string{"all"},
- AppId: "default",
- ServiceName: "TestServic1",
- })
- assert.NoError(t, err)
- assert.NotEqual(t, 0, len(resp.AllServicesDetail))
- assert.NotEqual(t, 0, resp.Statistics.Services.Count)
- assert.NotEqual(t, 0, resp.Statistics.Instances.Count)
- assert.NotEqual(t, 0, resp.Statistics.Apps.Count)
- })
-
- t.Run("unregister tested service & instance, should be passed", func(t
*testing.T) {
- err := datasource.GetMetadataManager().UnregisterInstance(ctx,
&pb.UnregisterInstanceRequest{
- ServiceId: serviceID,
- InstanceId: instanceID,
- })
- assert.NoError(t, err)
-
- err = datasource.GetMetadataManager().UnregisterService(ctx,
&pb.DeleteServiceRequest{
- ServiceId: serviceID,
- Force: true,
- })
- assert.NoError(t, err)
- })
-
- t.Run("get all services", func(t *testing.T) {
- log.Info("should be passed")
- resp, err :=
datasource.GetMetadataManager().ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
- Options: []string{"all"},
- })
- assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
-
- resp, err =
datasource.GetMetadataManager().ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
- Options: []string{""},
- })
- assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
-
- resp, err =
datasource.GetMetadataManager().ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
- Options: []string{"tags", "rules", "instances",
"schemas", "statistics"},
- })
- assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
-
- resp, err =
datasource.GetMetadataManager().ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
- Options: []string{"statistics"},
- })
- assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
-
- resp, err =
datasource.GetMetadataManager().ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
- Options: []string{"instances"},
- CountOnly: true,
- })
- assert.NoError(t, err)
- assert.Equal(t, pb.ResponseSuccess, resp.Response.GetCode())
- })
-}
-
-func TestService_Detail(t *testing.T) {
- var (
- serviceId string
- )
- ctx := getContext()
- defer datasource.GetMetadataManager().UnregisterService(ctx,
&pb.DeleteServiceRequest{ServiceId: serviceId, Force: true})
-
- t.Run("execute 'get detail' operation", func(t *testing.T) {
- log.Info("should be passed")
- resp, err :=
datasource.GetMetadataManager().RegisterService(ctx, &pb.CreateServiceRequest{
- 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)
- serviceId = resp.ServiceId
-
- _, err = datasource.GetMetadataManager().ModifySchema(ctx,
&pb.ModifySchemaRequest{
- ServiceId: serviceId,
- SchemaId: "schemaId",
- Schema: "detail",
- })
- assert.NoError(t, err)
-
- _, err = datasource.GetMetadataManager().RegisterInstance(ctx,
&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)
-
- err = datasource.GetMetadataManager().UnregisterService(ctx,
&pb.DeleteServiceRequest{
- ServiceId: serviceId,
- Force: true,
- })
- assert.NoError(t, err)
- })
-}
-
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")
diff --git a/server/resource/govern/govern_resource.go
b/server/resource/govern/govern_resource.go
index bc3189d5..eb5cc6d3 100644
--- a/server/resource/govern/govern_resource.go
+++ b/server/resource/govern/govern_resource.go
@@ -19,12 +19,14 @@ package govern
import (
"net/http"
+ "net/url"
"strings"
"github.com/apache/servicecomb-service-center/pkg/rest"
"github.com/apache/servicecomb-service-center/pkg/util"
governsvc
"github.com/apache/servicecomb-service-center/server/service/govern"
pb "github.com/go-chassis/cari/discovery"
+ "github.com/go-chassis/foundation/stringutil"
)
// Service 治理相关接口服务
@@ -78,6 +80,7 @@ func (res *Resource) ListService(w http.ResponseWriter, r
*http.Request) {
request.ServiceName = query.Get("serviceName")
request.Environment = query.Get("env")
request.WithShared = util.StringTRUE(query.Get("withShared"))
+ request.Properties = ParseProperties(query, "property")
countOnly := query.Get("countOnly")
if countOnly != "0" && countOnly != "1" && strings.TrimSpace(countOnly)
!= "" {
rest.WriteError(w, pb.ErrInvalidParams, "parameter countOnly
must be 1 or 0")
@@ -94,6 +97,21 @@ func (res *Resource) ListService(w http.ResponseWriter, r
*http.Request) {
rest.WriteResponse(w, r, nil, resp)
}
+func ParseProperties(query url.Values, key string) map[string]string {
+ propertyList := query[key]
+ properties := make(map[string]string, len(propertyList))
+ for _, kv := range propertyList {
+ if !strings.Contains(kv, ":") {
+ properties[kv] = ""
+ continue
+ }
+
+ k, v := stringutil.SplitToTwo(kv, ":")
+ properties[k] = v
+ }
+ return properties
+}
+
func (res *Resource) GetOverview(w http.ResponseWriter, r *http.Request) {
st, err := governsvc.GetOverview(r.Context(), &pb.GetServicesRequest{})
if err != nil {
diff --git a/server/resource/govern/govern_resource_test.go
b/server/resource/govern/govern_resource_test.go
index 1ce38542..c60421c7 100644
--- a/server/resource/govern/govern_resource_test.go
+++ b/server/resource/govern/govern_resource_test.go
@@ -21,8 +21,11 @@ import (
"context"
"encoding/json"
"io"
+ "io/ioutil"
"net/http"
"net/http/httptest"
+ "net/url"
+ "reflect"
"testing"
_ "github.com/apache/servicecomb-service-center/test"
@@ -43,6 +46,8 @@ func TestResource_GetServiceDetail(t *testing.T) {
service, err := discosvc.RegisterService(ctx,
&pb.CreateServiceRequest{Service: &pb.MicroService{
ServiceName: "get_service_detail",
+ Schemas: []string{"test"},
+ Properties: map[string]string{"test": "list"},
}})
assert.NoError(t, err)
serviceID := service.ServiceId
@@ -58,7 +63,10 @@ func TestResource_GetServiceDetail(t *testing.T) {
body, _ := io.ReadAll(w.Body)
err := json.Unmarshal(body, &resp)
assert.NoError(t, err)
- assert.Equal(t, serviceID, resp.Service.MicroService.ServiceId)
+ detail := resp.Service
+ assert.Equal(t, serviceID, detail.MicroService.ServiceId)
+ assert.NotEmpty(t, detail.MicroService.Schemas)
+ assert.NotEmpty(t, detail.MicroService.Properties)
})
t.Run("query not exist service detail, should fail", func(t *testing.T)
{
@@ -75,6 +83,8 @@ func TestResource_ListServiceDetail(t *testing.T) {
const serviceName = "list_service_detail"
service, err := discosvc.RegisterService(ctx,
&pb.CreateServiceRequest{Service: &pb.MicroService{
ServiceName: serviceName,
+ Schemas: []string{"test"},
+ Properties: map[string]string{"test": "list"},
}})
assert.NoError(t, err)
serviceID := service.ServiceId
@@ -90,7 +100,10 @@ func TestResource_ListServiceDetail(t *testing.T) {
body, _ := io.ReadAll(w.Body)
err := json.Unmarshal(body, &resp)
assert.NoError(t, err)
- assert.Equal(t, serviceID,
resp.AllServicesDetail[0].MicroService.ServiceId)
+ detail := resp.AllServicesDetail[0]
+ assert.Equal(t, serviceID, detail.MicroService.ServiceId)
+ assert.NotEmpty(t, detail.MicroService.Properties)
+ assert.Empty(t, detail.MicroService.Schemas)
assert.NotEqual(t, int64(0), resp.Statistics.Services.Count)
assert.NotEqual(t, int64(0), resp.Statistics.Apps.Count)
})
@@ -109,6 +122,49 @@ func TestResource_ListServiceDetail(t *testing.T) {
assert.NotEqual(t, int64(0), resp.Statistics.Services.Count)
assert.NotEqual(t, int64(0), resp.Statistics.Apps.Count)
})
+
+ t.Run("list service detail with properties filter, should ok", func(t
*testing.T) {
+ r, _ := http.NewRequest(http.MethodGet,
"/v4/default/govern/microservices?noCache=true&options=all&serviceName="+serviceName+"&property=test:list",
nil)
+ w := httptest.NewRecorder()
+ rest.GetRouter().ServeHTTP(w, r)
+ assert.Equal(t, http.StatusOK, w.Code)
+
+ var resp pb.GetServicesInfoResponse
+ body, _ := ioutil.ReadAll(w.Body)
+ err := json.Unmarshal(body, &resp)
+ assert.NoError(t, err)
+ assert.Equal(t, serviceID,
resp.AllServicesDetail[0].MicroService.ServiceId)
+ assert.NotEqual(t, int64(0), resp.Statistics.Services.Count)
+ assert.NotEqual(t, int64(0), resp.Statistics.Apps.Count)
+ })
+
+ t.Run("list service detail with only properties filter, should ok",
func(t *testing.T) {
+ r, _ := http.NewRequest(http.MethodGet,
"/v4/default/govern/microservices?noCache=true&options=all&property=test:list",
nil)
+ w := httptest.NewRecorder()
+ rest.GetRouter().ServeHTTP(w, r)
+ assert.Equal(t, http.StatusOK, w.Code)
+
+ var resp pb.GetServicesInfoResponse
+ body, _ := ioutil.ReadAll(w.Body)
+ err := json.Unmarshal(body, &resp)
+ assert.NoError(t, err)
+ assert.Equal(t, serviceID,
resp.AllServicesDetail[0].MicroService.ServiceId)
+ assert.NotEqual(t, int64(0), resp.Statistics.Services.Count)
+ assert.NotEqual(t, int64(0), resp.Statistics.Apps.Count)
+ })
+
+ t.Run("list service detail with not exist properties, should return
empty", func(t *testing.T) {
+ r, _ := http.NewRequest(http.MethodGet,
"/v4/default/govern/microservices?noCache=true&options=all&serviceName="+serviceName+"&property=none:none",
nil)
+ w := httptest.NewRecorder()
+ rest.GetRouter().ServeHTTP(w, r)
+ assert.Equal(t, http.StatusOK, w.Code)
+
+ var resp pb.GetServicesInfoResponse
+ body, _ := ioutil.ReadAll(w.Body)
+ err := json.Unmarshal(body, &resp)
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(resp.AllServicesDetail))
+ })
}
func TestResource_ListApp(t *testing.T) {
@@ -136,3 +192,33 @@ func TestResource_ListApp(t *testing.T) {
assert.Contains(t, resp.AppIds, "list_app_app")
})
}
+
+func TestParseProperties(t *testing.T) {
+ type args struct {
+ query url.Values
+ key string
+ }
+ tests := []struct {
+ name string
+ args args
+ want map[string]string
+ }{
+ {"invalid queries", args{nil, "any"}, map[string]string{}},
+ {"invalid queries", args{url.Values{}, "any"},
map[string]string{}},
+ {"invalid queries", args{url.Values{"a": {"b:a"}}, "other"},
map[string]string{}},
+ {"valid queries", args{url.Values{"a": {""}}, "a"},
map[string]string{"": ""}},
+ {"valid queries", args{url.Values{"a": {"b"}}, "a"},
map[string]string{"b": ""}},
+ {"valid queries", args{url.Values{"a": {"b:"}}, "a"},
map[string]string{"b": ""}},
+ {"valid queries", args{url.Values{"a": {":"}}, "a"},
map[string]string{"": ""}},
+ {"valid queries", args{url.Values{"a": {":a"}}, "a"},
map[string]string{"": "a"}},
+ {"valid queries", args{url.Values{"a": {"b:a"}}, "a"},
map[string]string{"b": "a"}},
+ {"valid queries", args{url.Values{"a": {"b:a", "c:d"}}, "a"},
map[string]string{"b": "a", "c": "d"}},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := govern.ParseProperties(tt.args.query,
tt.args.key); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("ParseProperties() = %v, want %v",
got, tt.want)
+ }
+ })
+ }
+}
diff --git a/server/server.go b/server/server.go
index fbef2fe2..ce06edd8 100644
--- a/server/server.go
+++ b/server/server.go
@@ -118,9 +118,8 @@ func (s *ServiceCenterServer) initDatasource() {
log.Error("", err)
}
},
- EnableCache: config.GetRegistry().EnableCache,
- InstanceTTL: config.GetRegistry().InstanceTTL,
- InstanceProperties:
config.GetStringMap("registry.instance.properties"),
+ EnableCache: config.GetRegistry().EnableCache,
+ InstanceTTL: config.GetRegistry().InstanceTTL,
}); err != nil {
log.Fatal("init datasource failed", err)
}
diff --git a/server/service/disco/retire_test.go
b/server/service/disco/retire_test.go
index c41fbc63..a66380bd 100644
--- a/server/service/disco/retire_test.go
+++ b/server/service/disco/retire_test.go
@@ -24,6 +24,7 @@ import (
"github.com/apache/servicecomb-service-center/datasource"
"github.com/apache/servicecomb-service-center/datasource/schema"
discosvc
"github.com/apache/servicecomb-service-center/server/service/disco"
+ "github.com/apache/servicecomb-service-center/server/service/govern"
"github.com/apache/servicecomb-service-center/test"
pb "github.com/go-chassis/cari/discovery"
"github.com/stretchr/testify/assert"
@@ -63,7 +64,7 @@ func TestRetireService(t *testing.T) {
err := discosvc.RetireService(ctx,
&datasource.RetirePlan{Reserve: 1})
assert.NoError(t, err)
- resp, err :=
datasource.GetMetadataManager().ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
+ resp, err := govern.ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
ServiceName: serviceIDPrefix,
})
assert.NoError(t, err)
diff --git a/server/service/govern/view.go b/server/service/govern/view.go
index d519cdde..2664bbec 100644
--- a/server/service/govern/view.go
+++ b/server/service/govern/view.go
@@ -24,14 +24,228 @@ import (
"github.com/apache/servicecomb-service-center/datasource"
"github.com/apache/servicecomb-service-center/pkg/log"
"github.com/apache/servicecomb-service-center/pkg/util"
+ "github.com/apache/servicecomb-service-center/server/config"
discosvc
"github.com/apache/servicecomb-service-center/server/service/disco"
"github.com/apache/servicecomb-service-center/server/service/validator"
pb "github.com/go-chassis/cari/discovery"
+ "github.com/jinzhu/copier"
)
+var defaultOptions = []string{"tags", "instances", "schemas", "dependencies"}
+
+type ServiceDetailOpt struct {
+ domainProject string
+ service *pb.MicroService
+ countOnly bool
+ options []string
+}
+
func ListServiceDetail(ctx context.Context, in *pb.GetServicesInfoRequest)
(*pb.GetServicesInfoResponse, error) {
ctx = util.WithCacheOnly(ctx)
- return datasource.GetMetadataManager().ListServiceDetail(ctx, in)
+
+ optionMap := make(map[string]struct{}, len(in.Options))
+ for _, opt := range in.Options {
+ optionMap[opt] = struct{}{}
+ }
+
+ options := make([]string, 0, len(optionMap))
+ if _, ok := optionMap["all"]; ok {
+ optionMap["statistics"] = struct{}{}
+ options = defaultOptions
+ } else {
+ for opt := range optionMap {
+ options = append(options, opt)
+ }
+ }
+
+ var st *pb.Statistics
+ if _, ok := optionMap["statistics"]; ok {
+ var err error
+ st, err = datasource.GetMetadataManager().Statistics(ctx,
in.WithShared)
+ if err != nil {
+ return nil, pb.NewError(pb.ErrInternal, err.Error())
+ }
+ if len(optionMap) == 1 {
+ return &pb.GetServicesInfoResponse{
+ Statistics: st,
+ }, nil
+ }
+ }
+
+ //获取所有服务
+ resp, err := discosvc.ListService(ctx, &pb.GetServicesRequest{})
+ if err != nil {
+ log.Error("get all services by domain failed", err)
+ return nil, pb.NewError(pb.ErrInternal, err.Error())
+ }
+ services := resp.Services
+
+ allServiceDetails := make([]*pb.ServiceDetail, 0, len(services))
+ domainProject := util.ParseDomainProject(ctx)
+ instanceProperties :=
config.GetStringMap("registry.instance.properties")
+ for _, service := range services {
+ if !filterServices(domainProject, in, service) {
+ continue
+ }
+
+ serviceDetail, err := getServiceDetailUtil(ctx,
ServiceDetailOpt{
+ domainProject: domainProject,
+ service: service,
+ countOnly: in.CountOnly,
+ options: options,
+ })
+ if err != nil {
+ return nil, pb.NewError(pb.ErrInternal, err.Error())
+ }
+ serviceDetail.MicroService = service
+ tmpServiceDetail, err := NewServiceOverview(serviceDetail,
instanceProperties)
+ if err != nil {
+ return nil, err
+ }
+ allServiceDetails = append(allServiceDetails, tmpServiceDetail)
+ }
+
+ return &pb.GetServicesInfoResponse{
+ AllServicesDetail: allServiceDetails,
+ Statistics: st,
+ }, nil
+}
+
+func getServiceDetailUtil(ctx context.Context, opts ServiceDetailOpt)
(*pb.ServiceDetail, error) {
+ service := opts.service
+ serviceID := service.ServiceId
+ serviceLogName := fmt.Sprintf("%s][%s/%s/%s/%s", service.ServiceId,
service.Environment, service.AppId, service.ServiceName, service.Version)
+ options := opts.options
+ serviceDetail := new(pb.ServiceDetail)
+ if opts.countOnly {
+ serviceDetail.Statics = new(pb.Statistics)
+ }
+
+ for _, opt := range options {
+ expr := opt
+ switch expr {
+ case "tags":
+ resp, err := discosvc.ListTag(ctx,
&pb.GetServiceTagsRequest{
+ ServiceId: serviceID,
+ })
+ if err != nil {
+ log.Error(fmt.Sprintf("get service[%s]'s all
tags failed", serviceLogName), err)
+ return nil, err
+ }
+ serviceDetail.Tags = resp.Tags
+ case "instances":
+ resp, err := discosvc.ListInstance(ctx,
&pb.GetInstancesRequest{
+ ProviderServiceId: serviceID,
+ })
+ if err != nil {
+ log.Error(fmt.Sprintf("get service[%s]'s all
instances failed", serviceLogName), err)
+ return nil, err
+ }
+ if opts.countOnly {
+ if err != nil {
+ log.Error(fmt.Sprintf("get number of
service[%s]'s instances failed", serviceLogName), err)
+ return nil, err
+ }
+ serviceDetail.Statics.Instances =
&pb.StInstance{
+ Count: int64(len(resp.Instances)),
+ }
+ continue
+ }
+ serviceDetail.Instances = resp.Instances
+ case "schemas":
+ schemas, err := discosvc.ListSchema(ctx,
&pb.GetAllSchemaRequest{
+ ServiceId: serviceID,
+ WithSchema: true,
+ })
+ if err != nil {
+ log.Error(fmt.Sprintf("get service[%s]'s all
schemas failed", serviceLogName), err)
+ return nil, err
+ }
+ serviceDetail.SchemaInfos = schemas
+ case "dependencies":
+ consumerResp, err := discosvc.ListConsumers(ctx,
&pb.GetDependenciesRequest{
+ ServiceId: serviceID,
+ NoSelf: true,
+ SameDomain: true,
+ })
+ if err != nil {
+ log.Error(fmt.Sprintf("get service[%s]'s all
consumers failed", serviceLogName), err)
+ return nil, err
+ }
+ providerResp, err := discosvc.ListProviders(ctx,
&pb.GetDependenciesRequest{
+ ServiceId: serviceID,
+ NoSelf: true,
+ SameDomain: true,
+ })
+ if err != nil {
+ log.Error(fmt.Sprintf("get service[%s]'s all
providers failed", serviceLogName), err)
+ return nil, err
+ }
+ serviceDetail.Consumers = consumerResp.Consumers
+ serviceDetail.Providers = providerResp.Providers
+ case "":
+ continue
+ default:
+ log.Error(fmt.Sprintf("request option[%s] is invalid",
opt), nil)
+ }
+ }
+ return serviceDetail, nil
+}
+
+func filterServices(domainProject string, request *pb.GetServicesInfoRequest,
service *pb.MicroService) bool {
+ if !request.WithShared &&
datasource.IsGlobal(pb.MicroServiceToKey(domainProject, service)) {
+ return false
+ }
+ if len(request.Environment) > 0 && request.Environment !=
service.Environment {
+ return false
+ }
+ if len(request.AppId) > 0 && request.AppId != service.AppId {
+ return false
+ }
+ if len(request.ServiceName) > 0 && request.ServiceName !=
service.ServiceName {
+ return false
+ }
+ if len(request.Properties) > 0 &&
!matchAllProperties(request.Properties, service) {
+ return false
+ }
+ return true
+}
+
+func matchAllProperties(properties map[string]string, service
*pb.MicroService) bool {
+ for k, v := range properties {
+ val, ok := service.Properties[k]
+ if !ok || v != val {
+ return false
+ }
+ }
+ return true
+}
+
+func NewServiceOverview(serviceDetail *pb.ServiceDetail, innerProperties
map[string]string) (*pb.ServiceDetail, error) {
+ tmpServiceDetail := &pb.ServiceDetail{}
+ err := copier.CopyWithOption(tmpServiceDetail, serviceDetail,
copier.Option{DeepCopy: true})
+ if err != nil {
+ return nil, pb.NewError(pb.ErrInternal, err.Error())
+ }
+ tmpServiceDetail.MicroService.Schemas = nil
+ instances := tmpServiceDetail.Instances
+ for _, instance := range instances {
+ instance.Properties =
removeCustomProperties(instance.Properties, innerProperties)
+ }
+ return tmpServiceDetail, nil
+}
+
+func removeCustomProperties(properties, innerProperties map[string]string)
map[string]string {
+ if len(innerProperties) == 0 {
+ return nil
+ }
+ props := make(map[string]string)
+ for k, v := range properties {
+ if _, ok := innerProperties[k]; ok {
+ props[k] = v
+ }
+ }
+ return props
}
func GetServiceDetail(ctx context.Context, in *pb.GetServiceRequest)
(*pb.ServiceDetail, error) {
diff --git a/server/service/govern/view_test.go
b/server/service/govern/view_test.go
index 70684fe1..608e4888 100644
--- a/server/service/govern/view_test.go
+++ b/server/service/govern/view_test.go
@@ -35,32 +35,52 @@ func getContext() context.Context {
}
func TestListServiceDetail(t *testing.T) {
+ ctx := getContext()
+ respC, err := disco.RegisterService(ctx, &pb.CreateServiceRequest{
+ Service: &pb.MicroService{
+ AppId: "govern_service_group",
+ ServiceName: "govern_service_graph",
+ Version: "1.0.0",
+ Level: "FRONT",
+ Status: pb.MS_UP,
+ },
+ })
+ assert.NoError(t, err)
+ assert.NotNil(t, respC)
+ defer disco.UnregisterService(ctx, &pb.DeleteServiceRequest{ServiceId:
respC.ServiceId, Force: true})
+
t.Run("when get all services, should be passed", func(t *testing.T) {
- resp, err := govern.ListServiceDetail(getContext(),
&pb.GetServicesInfoRequest{
+ resp, err := govern.ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
Options: []string{"all"},
})
assert.NoError(t, err)
assert.NotNil(t, resp)
+ assert.NotNil(t, resp.Statistics)
+ assert.NotNil(t, resp.AllServicesDetail)
- resp, err = govern.ListServiceDetail(getContext(),
&pb.GetServicesInfoRequest{
+ resp, err = govern.ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
Options: []string{""},
})
assert.NoError(t, err)
assert.NotNil(t, resp)
+ assert.Nil(t, resp.Statistics)
+ assert.NotNil(t, resp.AllServicesDetail)
- resp, err = govern.ListServiceDetail(getContext(),
&pb.GetServicesInfoRequest{
+ resp, err = govern.ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
Options: []string{"tags", "rules", "instances",
"schemas", "statistics"},
})
assert.NoError(t, err)
assert.NotNil(t, resp)
- resp, err = govern.ListServiceDetail(getContext(),
&pb.GetServicesInfoRequest{
+ resp, err = govern.ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
Options: []string{"statistics"},
})
assert.NoError(t, err)
assert.NotNil(t, resp)
+ assert.NotNil(t, resp.Statistics)
+ assert.Nil(t, resp.AllServicesDetail)
- resp, err = govern.ListServiceDetail(getContext(),
&pb.GetServicesInfoRequest{
+ resp, err = govern.ListServiceDetail(ctx,
&pb.GetServicesInfoRequest{
Options: []string{"instances"},
CountOnly: true,
})
@@ -69,19 +89,8 @@ func TestListServiceDetail(t *testing.T) {
})
t.Run("when get top graph, should be passed", func(t *testing.T) {
- respC, err := disco.RegisterService(getContext(),
&pb.CreateServiceRequest{
- Service: &pb.MicroService{
- AppId: "govern_service_group",
- ServiceName: "govern_service_graph",
- Version: "1.0.0",
- Level: "FRONT",
- Status: pb.MS_UP,
- },
- })
- assert.NoError(t, err)
- assert.NotNil(t, respC)
- graph, err := govern.Draw(getContext(), false)
+ graph, err := govern.Draw(ctx, false)
assert.NoError(t, err)
assert.NotEqual(t, 0, len(graph.Nodes))
})
@@ -176,3 +185,65 @@ func TestGetServiceDetail(t *testing.T) {
assert.Nil(t, respGetServiceDetail)
})
}
+
+func TestNewServiceOverview(t *testing.T) {
+ t.Run("no instances, should be ok", func(t *testing.T) {
+ _, err := govern.NewServiceOverview(&pb.ServiceDetail{
+ MicroService: &pb.MicroService{},
+ }, nil)
+ assert.NoError(t, err)
+
+ _, err = govern.NewServiceOverview(&pb.ServiceDetail{
+ MicroService: &pb.MicroService{},
+ Instances: []*pb.MicroServiceInstance{},
+ }, nil)
+ assert.NoError(t, err)
+ })
+
+ t.Run("has schema or service properties, should be ok", func(t
*testing.T) {
+ overview, err := govern.NewServiceOverview(&pb.ServiceDetail{
+ MicroService: &pb.MicroService{
+ Schemas: []string{"test"},
+ Properties: map[string]string{"test": "A"},
+ },
+ }, nil)
+ assert.NoError(t, err)
+ assert.Empty(t, overview.MicroService.Schemas)
+ assert.NotEmpty(t, overview.MicroService.Properties)
+ })
+
+ t.Run("has instance properties, should be ok", func(t *testing.T) {
+ overview, err := govern.NewServiceOverview(&pb.ServiceDetail{
+ MicroService: &pb.MicroService{},
+ Instances: []*pb.MicroServiceInstance{
+ {
+ Properties: map[string]string{"test":
"A"},
+ },
+ },
+ }, nil)
+ assert.NoError(t, err)
+ assert.Empty(t, overview.Instances[0].Properties)
+
+ overview, err = govern.NewServiceOverview(&pb.ServiceDetail{
+ MicroService: &pb.MicroService{},
+ Instances: []*pb.MicroServiceInstance{
+ {
+ Properties: map[string]string{"test":
"A"},
+ },
+ },
+ }, map[string]string{"inner": "B"})
+ assert.NoError(t, err)
+ assert.Empty(t, overview.Instances[0].Properties)
+
+ overview, err = govern.NewServiceOverview(&pb.ServiceDetail{
+ MicroService: &pb.MicroService{},
+ Instances: []*pb.MicroServiceInstance{
+ {
+ Properties: map[string]string{"test":
"A", "inner": "C"},
+ },
+ },
+ }, map[string]string{"inner": "B"})
+ assert.NoError(t, err)
+ assert.Equal(t, "C", overview.Instances[0].Properties["inner"])
+ })
+}