[ https://issues.apache.org/jira/browse/SCB-336?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16379680#comment-16379680 ]
ASF GitHub Bot commented on SCB-336: ------------------------------------ little-cui closed pull request #279: SCB-336 1.add ut about find instance with tag 2.optimize find api URL: https://github.com/apache/incubator-servicecomb-service-center/pull/279 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/pkg/rest/client.go b/pkg/rest/client.go index 2cd68abe..f5b6c009 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 a4529672..19f77a69 100644 --- a/server/service/instances.go +++ b/server/service/instances.go @@ -567,13 +567,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)" } // 版本规则 @@ -585,7 +584,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), @@ -617,7 +616,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 7a85869e..267635cd 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 b8b07744..f7a3dee1 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 @@ -162,54 +156,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 } ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org > Can not filter instances with service tags > ------------------------------------------ > > Key: SCB-336 > URL: https://issues.apache.org/jira/browse/SCB-336 > Project: Apache ServiceComb > Issue Type: Bug > Components: Service-Center > Reporter: little-cui > Assignee: little-cui > Priority: Major > Fix For: service-center-1.0.0-m2 > > -- This message was sent by Atlassian JIRA (v7.6.3#76005)