You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/02/28 02:28:59 UTC

[incubator-servicecomb-service-center] branch master updated: SCB-336 1.add ut about find instance with tag 2.optimize find api (#279)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new ad8f059  SCB-336 1.add ut about find instance with tag 2.optimize find api (#279)
ad8f059 is described below

commit ad8f059f8a57a1c531a33f14226d623188015776
Author: aseTo2016 <14...@qq.com>
AuthorDate: Wed Feb 28 10:28:57 2018 +0800

    SCB-336 1.add ut about find instance with tag 2.optimize find api (#279)
    
    * 1.add ut about find instance with tag
    2.optimize find api
    
    (cherry picked from commit 0e5cd8e)
    
    * 1.add ut about find instance with tag
    2.optimize find api
    
    * 1.add ut about find instance with tag
    2.optimize find api
    
    * 1.add ut about find instance with tag
    2.optimize find api
---
 pkg/rest/client.go               |   6 +-
 server/service/instances.go      |   7 +--
 server/service/tag_test.go       | 118 ++++++++++++++++++++++++++++++++++++++-
 server/service/util/rule_util.go | 118 +++++++++++++++++++++++----------------
 4 files changed, 193 insertions(+), 56 deletions(-)

diff --git a/pkg/rest/client.go b/pkg/rest/client.go
index 2cd68ab..f5b6c00 100644
--- a/pkg/rest/client.go
+++ b/pkg/rest/client.go
@@ -229,10 +229,10 @@ func (client *HttpClient) httpDo(method string, url string, headers map[string]s
 	var bodyReader io.Reader = nil
 	if body != nil {
 		if headers == nil || len(headers["Content-Type"]) == 0 {
-			// 如果请求头未传入Conent-Type,则按照json格式进行编码(如果是非json类型,需要自行在headers里指定类型)
+			// 如果请求头未传入Content-Type,则按照json格式进行编码(如果是非json类型,需要自行在headers里指定类型)
 			bodyBytes, err = json.Marshal(body)
 			if err != nil {
-				util.Logger().Errorf(err, "mashal object failed.")
+				util.Logger().Errorf(err, "marshal object failed.")
 				return status, result
 			}
 		} else {
@@ -293,7 +293,7 @@ func (client *HttpClient) HttpDo(method string, url string, headers map[string]s
 			// 如果请求头未传入Conent-Type,则按照json格式进行编码(如果是非json类型,需要自行在headers里指定类型)
 			bodyBytes, err = json.Marshal(body)
 			if err != nil {
-				util.Logger().Errorf(err, "mashal object failed.")
+				util.Logger().Errorf(err, "marshal object failed.")
 				return nil, err
 			}
 		} else {
diff --git a/server/service/instances.go b/server/service/instances.go
index 7008667..e387fb0 100644
--- a/server/service/instances.go
+++ b/server/service/instances.go
@@ -568,13 +568,12 @@ func (s *InstanceService) Find(ctx context.Context, in *pb.FindInstancesRequest)
 	if apt.IsShared(provider) {
 		// it means the shared micro-services must be the same env with SC.
 		provider.Environment = apt.Service.Environment
-		findFlag += "(shared services in " + provider.Environment + " environment)"
+		findFlag += "(provider is shared service in " + provider.Environment + " environment)"
 	} else {
 		// provider is not a shared micro-service,
 		// only allow shared micro-service instances found in different domains.
 		util.SetTargetDomainProject(ctx, util.ParseDomain(ctx), util.ParseProject(ctx))
 		provider.Tenant = util.ParseTargetDomainProject(ctx)
-		findFlag += "('" + provider.Environment + "' services of the same domain)"
 	}
 
 	// 版本规则
@@ -586,7 +585,7 @@ func (s *InstanceService) Find(ctx context.Context, in *pb.FindInstancesRequest)
 		}, err
 	}
 	if len(ids) == 0 {
-		mes := fmt.Sprintf("no provider matched, %s", findFlag)
+		mes := fmt.Sprintf("provider not exist, %s", findFlag)
 		util.Logger().Errorf(nil, "find instance failed, %s", mes)
 		return &pb.FindInstancesResponse{
 			Response: pb.CreateResponse(scerr.ErrServiceNotExists, mes),
@@ -618,7 +617,7 @@ func (s *InstanceService) Find(ctx context.Context, in *pb.FindInstancesRequest)
 	//维护version的规则,service name 可能是别名,所以重新获取
 	providerService, err := serviceUtil.GetService(ctx, provider.Tenant, ids[0])
 	if providerService == nil {
-		util.Logger().Errorf(err, "find instance failed, %s: no provider matched.", findFlag)
+		util.Logger().Errorf(err, "find instance failed, %s: provider %s not exist.", findFlag, ids[0])
 		return &pb.FindInstancesResponse{
 			Response: pb.CreateResponse(scerr.ErrServiceNotExists, "No provider matched."),
 		}, nil
diff --git a/server/service/tag_test.go b/server/service/tag_test.go
index 7a85869..267635c 100644
--- a/server/service/tag_test.go
+++ b/server/service/tag_test.go
@@ -191,7 +191,7 @@ var _ = Describe("'Tag' service", func() {
 
 	})
 
-	Describe("execute 'update' operartion", func() {
+	Describe("execute 'update' operation", func() {
 		var (
 			serviceId string
 		)
@@ -283,9 +283,123 @@ var _ = Describe("'Tag' service", func() {
 
 		})
 
+		Context("find instance, contain tag", func() {
+			It("should pass", func() {
+				By("create consumer")
+				resp, err := serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+					Service: &pb.MicroService{
+						AppId:       "find_inst_tag_group",
+						ServiceName: "find_inst_tag_consumer",
+						Version:     "1.0.0",
+						Level:       "FRONT",
+						Status:      pb.MS_UP,
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(resp.Response.Code).To(Equal(pb.Response_SUCCESS))
+				consumerId := resp.ServiceId
+
+				By("create provider")
+				resp, err = serviceResource.Create(getContext(), &pb.CreateServiceRequest{
+					Service: &pb.MicroService{
+						AppId:       "find_inst_tag_group",
+						ServiceName: "find_inst_tag_provider",
+						Version:     "1.0.1",
+						Level:       "FRONT",
+						Status:      pb.MS_UP,
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(resp.Response.Code).To(Equal(pb.Response_SUCCESS))
+				providerId := resp.ServiceId
+
+				addTagResp, err := serviceResource.AddTags(getContext(), &pb.AddServiceTagsRequest{
+					ServiceId: providerId,
+					Tags:      map[string]string{"filter_tag": "filter"},
+				})
+				Expect(err).To(BeNil())
+				Expect(addTagResp.Response.Code).To(Equal(pb.Response_SUCCESS))
+
+				instanceResp, err := instanceResource.Register(getContext(), &pb.RegisterInstanceRequest{
+					Instance: &pb.MicroServiceInstance{
+						ServiceId: providerId,
+						Endpoints: []string{
+							"findInstanceForTagFilter:127.0.0.1:8080",
+						},
+						HostName: "UT-HOST",
+						Status:   pb.MSI_UP,
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(instanceResp.Response.Code).To(Equal(pb.Response_SUCCESS))
+
+				findResp, err := instanceResource.Find(getContext(), &pb.FindInstancesRequest{
+					ConsumerServiceId: consumerId,
+					AppId:       "find_inst_tag_group",
+					ServiceName: "find_inst_tag_provider",
+					VersionRule: "1.0.0+",
+					Tags:        []string{"not-exist-tag"},
+				})
+				Expect(findResp.Response.Code).To(Equal(pb.Response_SUCCESS))
+				Expect(len(findResp.Instances)).To(Equal(0))
+
+				findResp, err = instanceResource.Find(getContext(), &pb.FindInstancesRequest{
+					ConsumerServiceId: consumerId,
+					AppId:       "find_inst_tag_group",
+					ServiceName: "find_inst_tag_provider",
+					VersionRule: "1.0.0+",
+					Tags:        []string{"filter_tag"},
+				})
+				Expect(err).To(BeNil())
+				Expect(findResp.Response.Code).To(Equal(pb.Response_SUCCESS))
+				Expect(findResp.Instances[0].InstanceId).To(Equal(instanceResp.InstanceId))
+
+				respAddRule, err := serviceResource.AddRule(getContext(), &pb.AddServiceRulesRequest{
+					ServiceId: providerId,
+					Rules: []*pb.AddOrUpdateServiceRule{
+						&pb.AddOrUpdateServiceRule{
+							RuleType: "WHITE",
+							Attribute: "tag_filter_tag",
+							Pattern: "f*",
+							Description: "test white",
+						},
+					},
+				})
+				Expect(err).To(BeNil())
+				Expect(respAddRule.Response.Code).To(Equal(pb.Response_SUCCESS))
+
+				findResp, err = instanceResource.Find(getContext(), &pb.FindInstancesRequest{
+					ConsumerServiceId: consumerId,
+					AppId:       "find_inst_tag_group",
+					ServiceName: "find_inst_tag_provider",
+					VersionRule: "1.0.0+",
+					Tags:        []string{"filter_tag"},
+				})
+				Expect(findResp.Response.Code).To(Equal(pb.Response_SUCCESS))
+				Expect(len(findResp.Instances)).To(Equal(0))
+
+				addTagResp, err = serviceResource.AddTags(getContext(), &pb.AddServiceTagsRequest{
+					ServiceId: consumerId,
+					Tags:      map[string]string{"filter_tag": "filter"},
+				})
+				Expect(err).To(BeNil())
+				Expect(addTagResp.Response.Code).To(Equal(pb.Response_SUCCESS))
+
+				findResp, err = instanceResource.Find(getContext(), &pb.FindInstancesRequest{
+					ConsumerServiceId: consumerId,
+					AppId:       "find_inst_tag_group",
+					ServiceName: "find_inst_tag_provider",
+					VersionRule: "1.0.0+",
+					Tags:        []string{"filter_tag"},
+				})
+				Expect(findResp.Response.Code).To(Equal(pb.Response_SUCCESS))
+				Expect(findResp.Instances[0].InstanceId).To(Equal(instanceResp.InstanceId))
+			})
+		})
+
 	})
 
-	Describe("execute 'delete' operartion", func() {
+	Describe("execute 'delete' operation", func() {
 		var (
 			serviceId string
 		)
diff --git a/server/service/util/rule_util.go b/server/service/util/rule_util.go
index 2ecabc0..df2047d 100644
--- a/server/service/util/rule_util.go
+++ b/server/service/util/rule_util.go
@@ -31,12 +31,6 @@ import (
 	"strings"
 )
 
-var tagRegEx *regexp.Regexp
-
-func init() {
-	tagRegEx, _ = regexp.Compile("tag_(.*)")
-}
-
 type RuleFilter struct {
 	DomainProject string
 	Provider      *pb.MicroService
@@ -161,54 +155,84 @@ func AllowAcrossDimension(ctx context.Context, providerService *pb.MicroService,
 	return nil
 }
 
-func MatchRules(rules []*pb.ServiceRule, service *pb.MicroService, serviceTags map[string]string) *scerr.Error {
-	if service == nil {
-		return scerr.NewError(scerr.ErrInvalidParams, "service is nil")
+func MatchRules(rulesOfProvider []*pb.ServiceRule, consumer *pb.MicroService, tagsOfConsumer map[string]string) *scerr.Error {
+	if consumer == nil {
+		return scerr.NewError(scerr.ErrInvalidParams, "consumer is nil")
 	}
 
-	v := reflect.Indirect(reflect.ValueOf(service))
+	isWhite := false
+	if len(rulesOfProvider) <= 0 {
+		return nil
+	}
+	if rulesOfProvider[0].RuleType == "WHITE" {
+		isWhite = true
+	}
+	if isWhite {
+		return patternWhiteList(rulesOfProvider, tagsOfConsumer, consumer)
+	}
+	return patternBlackList(rulesOfProvider, tagsOfConsumer, consumer)
+}
 
-	hasWhite := false
-	for _, rule := range rules {
-		var value string
-		if tagRegEx.MatchString(rule.Attribute) {
-			key := tagRegEx.FindStringSubmatch(rule.Attribute)[1]
-			value = serviceTags[key]
-			if len(value) == 0 {
-				util.Logger().Infof("can not find service %s tag '%s'", service.ServiceId, key)
-				continue
-			}
-		} else {
-			key := v.FieldByName(rule.Attribute)
-			if !key.IsValid() {
-				util.Logger().Errorf(nil, "can not find service %s field '%s', rule %s",
-					service.ServiceId, rule.Attribute, rule.RuleId)
-				return scerr.NewError(scerr.ErrInternal, fmt.Sprintf("Can not find field '%s'", rule.Attribute))
-			}
-			value = key.String()
+func patternWhiteList(rulesOfProvider []*pb.ServiceRule, tagsOfConsumer map[string]string, consumer *pb.MicroService) *scerr.Error {
+	v := reflect.Indirect(reflect.ValueOf(consumer))
+	consumerId := consumer.ServiceId
+	for _, rule := range rulesOfProvider {
+		value, err := parsePattern(v, rule, tagsOfConsumer, consumerId)
+		if err != nil {
+			return err
+		}
+		if len(value) == 0 {
+			continue
+		}
+
+		match, _ := regexp.MatchString(rule.Pattern, value)
+		if match {
+			util.Logger().Infof("consumer %s match white list, rule.Pattern is %s, value is %s",
+				consumerId, rule.Pattern, value)
+			return nil
 		}
+	}
+	return scerr.NewError(scerr.ErrPermissionDeny, "Not found in white list")
+}
 
-		switch rule.RuleType {
-		case "WHITE":
-			hasWhite = true
-			match, _ := regexp.MatchString(rule.Pattern, value)
-			if match {
-				util.Logger().Infof("service %s match white list, rule.Pattern is %s, value is %s",
-					service.ServiceId, rule.Pattern, value)
-				return nil
-			}
-		case "BLACK":
-			match, _ := regexp.MatchString(rule.Pattern, value)
-			if match {
-				util.Logger().Infof("service %s match black list, rule.Pattern is %s, value is %s",
-					service.ServiceId, rule.Pattern, value)
-				return scerr.NewError(scerr.ErrPermissionDeny, "Found in black list")
-			}
+func parsePattern(v reflect.Value, rule *pb.ServiceRule, tagsOfConsumer map[string]string, consumerId string) (string, *scerr.Error) {
+	if strings.HasPrefix(rule.Attribute, "tag_") {
+		key := rule.Attribute[4:]
+		value := tagsOfConsumer[key]
+		if len(value) == 0 {
+			util.Logger().Infof("can not find service %s tag '%s'", consumerId, key)
 		}
+		return value, nil
+	}
+	key := v.FieldByName(rule.Attribute)
+	if !key.IsValid() {
+		util.Logger().Errorf(nil, "can not find service %s field '%s', rule %s",
+			consumerId, rule.Attribute, rule.RuleId)
+		return "", scerr.NewError(scerr.ErrInternal, fmt.Sprintf("Can not find field '%s'", rule.Attribute))
 	}
-	if hasWhite {
-		util.Logger().Infof("service %s do not match white list", service.ServiceId)
-		return scerr.NewError(scerr.ErrPermissionDeny, "Not found in white list")
+	return key.String(), nil
+
+}
+
+func patternBlackList(rulesOfProvider []*pb.ServiceRule, tagsOfConsumer map[string]string, consumer *pb.MicroService) *scerr.Error {
+	v := reflect.Indirect(reflect.ValueOf(consumer))
+	consumerId := consumer.ServiceId
+	for _, rule := range rulesOfProvider {
+		var value string
+		value, err := parsePattern(v, rule, tagsOfConsumer, consumerId)
+		if err != nil {
+			return err
+		}
+		if len(value) == 0 {
+			continue
+		}
+
+		match, _ := regexp.MatchString(rule.Pattern, value)
+		if match {
+			util.Logger().Infof("no permission to access, consumer %s match black list, rule.Pattern is %s, value is %s",
+				consumerId, rule.Pattern, value)
+			return scerr.NewError(scerr.ErrPermissionDeny, "Found in black list")
+		}
 	}
 	return nil
 }

-- 
To stop receiving notification emails like this one, please contact
littlecui@apache.org.