support take effect on api level (#1150)

This commit is contained in:
rinfx
2024-07-24 19:23:55 +08:00
committed by GitHub
parent f6ee4ed166
commit 8f483518a9
2 changed files with 65 additions and 21 deletions

View File

@@ -30,6 +30,7 @@ const (
Route Category = iota
Host
Service
RoutePrefix
)
type MatchType int
@@ -41,10 +42,11 @@ const (
)
const (
RULES_KEY = "_rules_"
MATCH_ROUTE_KEY = "_match_route_"
MATCH_DOMAIN_KEY = "_match_domain_"
MATCH_SERVICE_KEY = "_match_service_"
RULES_KEY = "_rules_"
MATCH_ROUTE_KEY = "_match_route_"
MATCH_DOMAIN_KEY = "_match_domain_"
MATCH_SERVICE_KEY = "_match_service_"
MATCH_ROUTE_PREFIX_KEY = "_match_route_prefix_"
)
type HostMatcher struct {
@@ -53,11 +55,12 @@ type HostMatcher struct {
}
type RuleConfig[PluginConfig any] struct {
category Category
routes map[string]struct{}
services map[string]struct{}
hosts []HostMatcher
config PluginConfig
category Category
routes map[string]struct{}
services map[string]struct{}
routePrefixs map[string]struct{}
hosts []HostMatcher
config PluginConfig
}
type RuleMatcher[PluginConfig any] struct {
@@ -92,6 +95,14 @@ func (m RuleMatcher[PluginConfig]) GetMatchConfig() (*PluginConfig, error) {
return &rule.config, nil
}
}
// category == RoutePrefix
if rule.category == RoutePrefix {
for routePrefix := range rule.routePrefixs {
if strings.HasPrefix(string(routeName), routePrefix) {
return &rule.config, nil
}
}
}
// category == Cluster
if m.serviceMatch(rule, string(serviceName)) {
return &rule.config, nil
@@ -152,18 +163,22 @@ func (m *RuleMatcher[PluginConfig]) ParseRuleConfig(config gjson.Result,
rule.routes = m.parseRouteMatchConfig(ruleJson)
rule.hosts = m.parseHostMatchConfig(ruleJson)
rule.services = m.parseServiceMatchConfig(ruleJson)
rule.routePrefixs = m.parseRoutePrefixMatchConfig(ruleJson)
noRoute := len(rule.routes) == 0
noHosts := len(rule.hosts) == 0
noService := len(rule.services) == 0
if boolToInt(noRoute)+boolToInt(noService)+boolToInt(noHosts) != 2 {
return errors.New("there is only one of '_match_route_', '_match_domain_' and '_match_service_' can present in configuration.")
noRoutePrefix := len(rule.routePrefixs) == 0
if boolToInt(noRoute)+boolToInt(noService)+boolToInt(noHosts)+boolToInt(noRoutePrefix) != 3 {
return errors.New("there is only one of '_match_route_', '_match_domain_', '_match_service_' and '_match_route_prefix_' can present in configuration.")
}
if !noRoute {
rule.category = Route
} else if !noHosts {
rule.category = Host
} else {
} else if !noService {
rule.category = Service
} else {
rule.category = RoutePrefix
}
m.ruleConfig = append(m.ruleConfig, rule)
}
@@ -182,6 +197,18 @@ func (m RuleMatcher[PluginConfig]) parseRouteMatchConfig(config gjson.Result) ma
return routes
}
func (m RuleMatcher[PluginConfig]) parseRoutePrefixMatchConfig(config gjson.Result) map[string]struct{} {
keys := config.Get(MATCH_ROUTE_PREFIX_KEY).Array()
routePrefixs := make(map[string]struct{})
for _, item := range keys {
routePrefix := item.String()
if routePrefix != "" {
routePrefixs[routePrefix] = struct{}{}
}
}
return routePrefixs
}
func (m RuleMatcher[PluginConfig]) parseServiceMatchConfig(config gjson.Result) map[string]struct{} {
keys := config.Get(MATCH_SERVICE_KEY).Array()
clusters := make(map[string]struct{})

View File

@@ -229,7 +229,7 @@ func TestParseRuleConfig(t *testing.T) {
},
{
name: "rules config",
config: `{"_rules_":[{"_match_domain_":["*.example.com","www.*","*","www.abc.com"],"name":"john", "age":18},{"_match_route_":["test1","test2"],"name":"ann", "age":16},{"_match_service_":["test1.dns","test2.static:8080"],"name":"ann", "age":16}]}`,
config: `{"_rules_":[{"_match_domain_":["*.example.com","www.*","*","www.abc.com"],"name":"john", "age":18},{"_match_route_":["test1","test2"],"name":"ann", "age":16},{"_match_service_":["test1.dns","test2.static:8080"],"name":"ann", "age":16},{"_match_route_prefix_":["api1","api2"],"name":"ann", "age":16}]}`,
expected: RuleMatcher[customConfig]{
ruleConfig: []RuleConfig[customConfig]{
{
@@ -252,8 +252,9 @@ func TestParseRuleConfig(t *testing.T) {
host: "www.abc.com",
},
},
routes: map[string]struct{}{},
services: map[string]struct{}{},
routes: map[string]struct{}{},
services: map[string]struct{}{},
routePrefixs: map[string]struct{}{},
config: customConfig{
name: "john",
age: 18,
@@ -265,7 +266,8 @@ func TestParseRuleConfig(t *testing.T) {
"test1": {},
"test2": {},
},
services: map[string]struct{}{},
services: map[string]struct{}{},
routePrefixs: map[string]struct{}{},
config: customConfig{
name: "ann",
age: 16,
@@ -273,11 +275,25 @@ func TestParseRuleConfig(t *testing.T) {
},
{
category: Service,
routes: map[string]struct{}{},
services: map[string]struct{}{
"test1.dns": {},
"test2.static:8080": {},
},
routes: map[string]struct{}{},
routePrefixs: map[string]struct{}{},
config: customConfig{
name: "ann",
age: 16,
},
},
{
category: RoutePrefix,
routes: map[string]struct{}{},
services: map[string]struct{}{},
routePrefixs: map[string]struct{}{
"api1": {},
"api2": {},
},
config: customConfig{
name: "ann",
age: 16,
@@ -294,17 +310,17 @@ func TestParseRuleConfig(t *testing.T) {
{
name: "invalid rule",
config: `{"_rules_":[{"_match_domain_":["*"],"_match_route_":["test"]}]}`,
errMsg: "there is only one of '_match_route_', '_match_domain_' and '_match_service_' can present in configuration.",
errMsg: "there is only one of '_match_route_', '_match_domain_', '_match_service_' and '_match_route_prefix_' can present in configuration.",
},
{
name: "invalid rule",
config: `{"_rules_":[{"_match_domain_":["*"],"_match_service_":["test.dns"]}]}`,
errMsg: "there is only one of '_match_route_', '_match_domain_' and '_match_service_' can present in configuration.",
errMsg: "there is only one of '_match_route_', '_match_domain_', '_match_service_' and '_match_route_prefix_' can present in configuration.",
},
{
name: "invalid rule",
config: `{"_rules_":[{"age":16}]}`,
errMsg: "there is only one of '_match_route_', '_match_domain_' and '_match_service_' can present in configuration.",
errMsg: "there is only one of '_match_route_', '_match_domain_', '_match_service_' and '_match_route_prefix_' can present in configuration.",
},
}
for _, c := range cases {
@@ -378,7 +394,8 @@ func TestParseOverrideConfig(t *testing.T) {
"r1": {},
"r2": {},
},
services: map[string]struct{}{},
services: map[string]struct{}{},
routePrefixs: map[string]struct{}{},
config: completeConfig{
consumers: []string{"c1", "c2", "c3"},
allow: []string{"c1", "c3"},