github.com/polarismesh/polaris@v1.17.8/cache/service/router_rule_query.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package service
    19  
    20  import (
    21  	"sort"
    22  	"strings"
    23  
    24  	apitraffic "github.com/polarismesh/specification/source/go/api/v1/traffic_manage"
    25  
    26  	types "github.com/polarismesh/polaris/cache/api"
    27  	"github.com/polarismesh/polaris/common/model"
    28  	"github.com/polarismesh/polaris/common/utils"
    29  )
    30  
    31  // forceUpdate 更新配置
    32  func (rc *routingConfigCache) forceUpdate() error {
    33  	if err := rc.Update(); err != nil {
    34  		return err
    35  	}
    36  	return nil
    37  }
    38  
    39  func queryRoutingRuleV2ByService(rule *model.ExtendRouterConfig, sourceNamespace, sourceService,
    40  	destNamespace, destService string, both bool) bool {
    41  	var (
    42  		sourceFind bool
    43  		destFind   bool
    44  	)
    45  
    46  	hasSourceSvc := len(sourceService) != 0
    47  	hasSourceNamespace := len(sourceNamespace) != 0
    48  	hasDestSvc := len(destService) != 0
    49  	hasDestNamespace := len(destNamespace) != 0
    50  
    51  	sourceService, isWildSourceSvc := utils.ParseWildName(sourceService)
    52  	sourceNamespace, isWildSourceNamespace := utils.ParseWildName(sourceNamespace)
    53  	destService, isWildDestSvc := utils.ParseWildName(destService)
    54  	destNamespace, isWildDestNamespace := utils.ParseWildName(destNamespace)
    55  
    56  	for i := range rule.RuleRouting.Rules {
    57  		subRule := rule.RuleRouting.Rules[i]
    58  		sources := subRule.GetSources()
    59  		if hasSourceNamespace || hasSourceSvc {
    60  			for i := range sources {
    61  				item := sources[i]
    62  				if hasSourceSvc {
    63  					if isWildSourceSvc {
    64  						if !strings.Contains(item.Service, sourceService) {
    65  							continue
    66  						}
    67  					} else if item.Service != sourceService {
    68  						continue
    69  					}
    70  				}
    71  				if hasSourceNamespace {
    72  					if isWildSourceNamespace {
    73  						if !strings.Contains(item.Namespace, sourceNamespace) {
    74  							continue
    75  						}
    76  					} else if item.Namespace != sourceNamespace {
    77  						continue
    78  					}
    79  				}
    80  				sourceFind = true
    81  				break
    82  			}
    83  		}
    84  
    85  		destinations := subRule.GetDestinations()
    86  		if hasDestNamespace || hasDestSvc {
    87  			for i := range destinations {
    88  				item := destinations[i]
    89  				if hasDestSvc {
    90  					if isWildDestSvc && !strings.Contains(item.Service, destService) {
    91  						continue
    92  					}
    93  					if item.Service != destService {
    94  						continue
    95  					}
    96  				}
    97  				if hasDestNamespace {
    98  					if isWildDestNamespace && !strings.Contains(item.Namespace, destNamespace) {
    99  						continue
   100  					}
   101  					if item.Namespace != destNamespace {
   102  						continue
   103  					}
   104  				}
   105  				destFind = true
   106  				break
   107  			}
   108  		}
   109  
   110  		if both {
   111  			if sourceFind && destFind {
   112  				return true
   113  			}
   114  		} else if sourceFind || destFind {
   115  			return true
   116  		}
   117  	}
   118  	return false
   119  }
   120  
   121  // QueryRoutingConfigsV2 Query Route Configuration List
   122  func (rc *routingConfigCache) QueryRoutingConfigsV2(args *types.RoutingArgs) (uint32, []*model.ExtendRouterConfig, error) {
   123  	if err := rc.forceUpdate(); err != nil {
   124  		return 0, nil, err
   125  	}
   126  	hasSourceQuery := len(args.SourceService) != 0 || len(args.SourceNamespace) != 0
   127  	hasDestQuery := len(args.DestinationService) != 0 || len(args.DestinationNamespace) != 0
   128  
   129  	res := make([]*model.ExtendRouterConfig, 0, 8)
   130  
   131  	var process = func(_ string, routeRule *model.ExtendRouterConfig) {
   132  		if args.ID != "" && args.ID != routeRule.ID {
   133  			return
   134  		}
   135  
   136  		if routeRule.GetRoutingPolicy() == apitraffic.RoutingPolicy_RulePolicy {
   137  			if args.Namespace != "" && args.Service != "" {
   138  				if !queryRoutingRuleV2ByService(routeRule, args.Namespace, args.Service,
   139  					args.Namespace, args.Service, false) {
   140  					return
   141  				}
   142  			}
   143  
   144  			if hasSourceQuery || hasDestQuery {
   145  				if !queryRoutingRuleV2ByService(routeRule, args.SourceNamespace, args.SourceService, args.DestinationNamespace,
   146  					args.DestinationService, hasSourceQuery && hasDestQuery) {
   147  					return
   148  				}
   149  			}
   150  		}
   151  
   152  		if args.Name != "" {
   153  			name, isWild := utils.ParseWildName(args.Name)
   154  			if isWild {
   155  				if !strings.Contains(routeRule.Name, name) {
   156  					return
   157  				}
   158  			} else if args.Name != routeRule.Name {
   159  				return
   160  			}
   161  		}
   162  
   163  		if args.Enable != nil && *args.Enable != routeRule.Enable {
   164  			return
   165  		}
   166  
   167  		res = append(res, routeRule)
   168  	}
   169  
   170  	rc.IteratorRouterRule(func(key string, value *model.ExtendRouterConfig) {
   171  		process(key, value)
   172  	})
   173  
   174  	amount, routings := rc.sortBeforeTrim(res, args)
   175  	return amount, routings, nil
   176  }
   177  
   178  func (rc *routingConfigCache) sortBeforeTrim(routings []*model.ExtendRouterConfig,
   179  	args *types.RoutingArgs) (uint32, []*model.ExtendRouterConfig) {
   180  	amount := uint32(len(routings))
   181  	if args.Offset >= amount || args.Limit == 0 {
   182  		return amount, nil
   183  	}
   184  	sort.Slice(routings, func(i, j int) bool {
   185  		asc := strings.ToLower(args.OrderType) == "asc" || args.OrderType == ""
   186  		if strings.ToLower(args.OrderField) == "priority" {
   187  			return orderByRoutingPriority(routings[i], routings[j], asc)
   188  		}
   189  		return orderByRoutingModifyTime(routings[i], routings[j], asc)
   190  	})
   191  	endIdx := args.Offset + args.Limit
   192  	if endIdx > amount {
   193  		endIdx = amount
   194  	}
   195  	return amount, routings[args.Offset:endIdx]
   196  }
   197  
   198  func orderByRoutingPriority(a, b *model.ExtendRouterConfig, asc bool) bool {
   199  	if a.Priority < b.Priority {
   200  		return asc
   201  	}
   202  	if a.Priority > b.Priority {
   203  		// false && asc always false
   204  		return false
   205  	}
   206  	return strings.Compare(a.ID, b.ID) < 0 && asc
   207  }
   208  
   209  func orderByRoutingModifyTime(a, b *model.ExtendRouterConfig, asc bool) bool {
   210  	if a.ModifyTime.After(b.ModifyTime) {
   211  		return asc
   212  	}
   213  	if a.ModifyTime.Before(b.ModifyTime) {
   214  		// false && asc always false
   215  		return false
   216  	}
   217  	return strings.Compare(a.ID, b.ID) < 0 && asc
   218  }