From 468187409db242ef44e7015bac2c8ae63fb0a710 Mon Sep 17 00:00:00 2001 From: william feng <> Date: Sat, 11 Jul 2020 16:11:02 +0800 Subject: [PATCH 01/10] add scope and key support for condition router --- cluster/router/condition/file.go | 5 +- cluster/router/condition/router_rule.go | 5 +- cluster/router/condition/router_rule_test.go | 26 ++++++++- cluster/router/condition/router_test.go | 60 ++++++++++++++++++++ cluster/router/tag/router_rule.go | 2 +- common/constant/key.go | 9 ++- 6 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 cluster/router/condition/router_test.go diff --git a/cluster/router/condition/file.go b/cluster/router/condition/file.go index eabdf1c263..85658e7eb3 100644 --- a/cluster/router/condition/file.go +++ b/cluster/router/condition/file.go @@ -71,7 +71,10 @@ func (f *FileConditionRouter) URL() common.URL { common.WithParamsValue(constant.RouterPriority, strconv.Itoa(routerRule.Priority)), common.WithParamsValue(constant.RULE_KEY, base64.URLEncoding.EncodeToString([]byte(rule))), common.WithParamsValue(constant.ROUTER_KEY, constant.CONDITION_ROUTE_PROTOCOL), - common.WithParamsValue(constant.CATEGORY_KEY, constant.ROUTERS_CATEGORY)) + common.WithParamsValue(constant.CATEGORY_KEY, constant.ROUTERS_CATEGORY), + common.WithParamsValue(constant.RouterRuleKey, routerRule.Key), + common.WithParamsValue(constant.RouterScope, routerRule.Scope), + ) }) return f.url } diff --git a/cluster/router/condition/router_rule.go b/cluster/router/condition/router_rule.go index ce397d6cc0..f8c2c3ed0d 100644 --- a/cluster/router/condition/router_rule.go +++ b/cluster/router/condition/router_rule.go @@ -26,6 +26,7 @@ import ( ) import ( + "github.com/apache/dubbo-go/common/constant" "github.com/apache/dubbo-go/cluster/router" "github.com/apache/dubbo-go/common" "github.com/apache/dubbo-go/common/yaml" @@ -33,7 +34,7 @@ import ( // RouterRule RouterRule config read from config file or config center type RouterRule struct { - router.BaseRouterRule `yaml:",inline""` + router.BaseRouterRule `yaml:",inline"` Conditions []string } @@ -57,7 +58,7 @@ func getRule(rawRule string) (*RouterRule, error) { return r, err } r.RawRule = rawRule - if len(r.Conditions) != 0 { + if len(r.Conditions) != 0 && r.Key != "" && (r.Scope == constant.RouterApplicationScope || r.Scope == constant.RouterServiceScope){ r.Valid = true } diff --git a/cluster/router/condition/router_rule_test.go b/cluster/router/condition/router_rule_test.go index 675acaec91..1376058ed3 100644 --- a/cluster/router/condition/router_rule_test.go +++ b/cluster/router/condition/router_rule_test.go @@ -32,6 +32,7 @@ import ( func TestGetRule(t *testing.T) { testyml := ` scope: application +key: test-provider runtime: true force: false conditions: @@ -50,10 +51,31 @@ conditions: assert.True(t, rule.Runtime) assert.Equal(t, false, rule.Force) assert.Equal(t, testyml, rule.RawRule) - assert.True(t, true, rule.Valid) + assert.True(t, rule.Valid) assert.Equal(t, false, rule.Enabled) assert.Equal(t, false, rule.Dynamic) - assert.Equal(t, "", rule.Key) + assert.Equal(t, "test-provider", rule.Key) + + testyml = ` +key: test-provider +runtime: true +force: false +conditions: + - > + method!=sayHello =>` + rule, e = getRule(testyml) + assert.Nil(t, e) + assert.False(t, rule.Valid) + + testyml = ` +scope: noApplication +key: test-provider +conditions: + - > + method!=sayHello =>` + rule, e = getRule(testyml) + assert.Nil(t, e) + assert.False(t, rule.Valid) } func TestIsMatchGlobPattern(t *testing.T) { diff --git a/cluster/router/condition/router_test.go b/cluster/router/condition/router_test.go new file mode 100644 index 0000000000..151f6ccfca --- /dev/null +++ b/cluster/router/condition/router_test.go @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package condition + + import ( + "testing" + ) + + import ( + "github.com/stretchr/testify/assert" + ) + + import ( + "github.com/dubbogo/gost/container/set" + ) + + func TestParseRule(t *testing.T) { + testString := `` + matchPair, err := parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair, make(map[string]MatchPair, 16)) + + testString = `method!=sayHello&application=sayGoodBye` + matchPair, err = parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet("sayHello")) + assert.EqualValues(t, matchPair["application"].Matches, gxset.NewSet("sayGoodBye")) + + testString = `noRule` + matchPair, err = parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair["noRule"].Mismatches, gxset.NewSet()) + assert.EqualValues(t, matchPair["noRule"].Matches, gxset.NewSet()) + + testString = `method!=sayHello,sayGoodBye` + matchPair, err = parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet(`sayHello`, `sayGoodBye`)) + + testString = `method!=sayHello,sayGoodDay=sayGoodBye` + matchPair, err = parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet(`sayHello`, `sayGoodDay`)) + assert.EqualValues(t, matchPair["method"].Matches, gxset.NewSet(`sayGoodBye`)) + } \ No newline at end of file diff --git a/cluster/router/tag/router_rule.go b/cluster/router/tag/router_rule.go index 926446dcb2..fcf5542fdd 100644 --- a/cluster/router/tag/router_rule.go +++ b/cluster/router/tag/router_rule.go @@ -24,7 +24,7 @@ import ( // RouterRule RouterRule config read from config file or config center type RouterRule struct { - router.BaseRouterRule `yaml:",inline""` + router.BaseRouterRule `yaml:",inline"` } func getRule(rawRule string) (*RouterRule, error) { diff --git a/common/constant/key.go b/common/constant/key.go index cd23dd0f1a..48d7a6dd10 100644 --- a/common/constant/key.go +++ b/common/constant/key.go @@ -196,7 +196,14 @@ const ( RouterEnabled = "enabled" // Priority Priority key in router module RouterPriority = "priority" - + // RouterScope Scope key in router module + RouterScope = "scope" + // RouterApplicationScope Scope key in router module + RouterApplicationScope = "application" + // RouterServiceScope Scope key in router module + RouterServiceScope = "service" + // RouterRuleKey defines the key of the router, service's/application's name + RouterRuleKey = "key" // ForceUseTag is the tag in attachment ForceUseTag = "dubbo.force.tag" Tagkey = "dubbo.tag" From 08a087706d85dd1c0f8e6178b790e0203045839e Mon Sep 17 00:00:00 2001 From: william feng <> Date: Sat, 18 Jul 2020 23:33:29 +0800 Subject: [PATCH 02/10] enable digesting multiple router rule in router_config.yml --- common/yaml/yaml.go | 10 +++++++-- config/router_config.go | 28 +++++++++++++++++++++---- config/router_config_test.go | 6 ++++++ config/service_config_test.go | 2 +- config/testdata/router_config.yml | 13 +++++++----- config/testdata/router_config_error.yml | 11 +++++----- config/testdata/router_multi_config.yml | 16 ++++++++++++++ 7 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 config/testdata/router_multi_config.yml diff --git a/common/yaml/yaml.go b/common/yaml/yaml.go index 5edda1b3c7..d7e1ca4e89 100644 --- a/common/yaml/yaml.go +++ b/common/yaml/yaml.go @@ -27,7 +27,7 @@ import ( "gopkg.in/yaml.v2" ) -// loadYMLConfig Load yml config byte from file +// LoadYMLConfig Load yml config byte from file func LoadYMLConfig(confProFile string) ([]byte, error) { if len(confProFile) == 0 { return nil, perrors.Errorf("application configure(provider) file name is nil") @@ -40,7 +40,7 @@ func LoadYMLConfig(confProFile string) ([]byte, error) { return ioutil.ReadFile(confProFile) } -// unmarshalYMLConfig Load yml config byte from file, then unmarshal to object +// UnmarshalYMLConfig Load yml config byte from file, then unmarshal to object func UnmarshalYMLConfig(confProFile string, out interface{}) ([]byte, error) { confFileStream, err := LoadYMLConfig(confProFile) if err != nil { @@ -49,6 +49,12 @@ func UnmarshalYMLConfig(confProFile string, out interface{}) ([]byte, error) { return confFileStream, yaml.Unmarshal(confFileStream, out) } +//UnmarshalYML unmarshals decodes the first document found within the in byte slice and assigns decoded values into the out value. func UnmarshalYML(data []byte, out interface{}) error { return yaml.Unmarshal(data, out) } + +// MarshalYML serializes the value provided into a YAML document. +func MarshalYML(in interface{}) ([]byte, error) { + return yaml.Marshal(in) +} diff --git a/config/router_config.go b/config/router_config.go index 16a2bec918..e9cd5dc749 100644 --- a/config/router_config.go +++ b/config/router_config.go @@ -23,6 +23,7 @@ import ( ) import ( + "github.com/apache/dubbo-go/cluster/router" "github.com/apache/dubbo-go/common/extension" "github.com/apache/dubbo-go/common/logger" "github.com/apache/dubbo-go/common/yaml" @@ -32,16 +33,35 @@ var ( routerURLSet = gxset.NewSet() ) +type LocalRouterRules struct { + RouterRules []interface{} `yaml:"routerRules"` +} // RouterInit Load config file to init router config func RouterInit(confRouterFile string) error { - fileRouterFactories := extension.GetFileRouterFactories() bytes, err := yaml.LoadYMLConfig(confRouterFile) if err != nil { return perrors.Errorf("ioutil.ReadFile(file:%s) = error:%v", confRouterFile, perrors.WithStack(err)) } - logger.Warnf("get fileRouterFactories len{%+v})", len(fileRouterFactories)) - for k, factory := range fileRouterFactories { - r, e := factory.NewFileRouter(bytes) + routerRules := &LocalRouterRules{} + err = yaml.UnmarshalYML(bytes, routerRules) + if err != nil { + return perrors.Errorf("Load router file %s failed due to error: %v", confRouterFile, perrors.WithStack(err)) + } + if len(routerRules.RouterRules) == 0 { + return perrors.Errorf("No router configurations in file %s", confRouterFile) + } + fileRouterFactories := extension.GetFileRouterFactories() + for _, v := range routerRules.RouterRules { + content, _ := yaml.MarshalYML(v) + err = initRouterConfig(content, fileRouterFactories) + } + return err +} + +func initRouterConfig (content []byte,factories map[string]router.FilePriorityRouterFactory) error { + logger.Warnf("get fileRouterFactories len{%+v})", len(factories)) + for k, factory := range factories { + r, e := factory.NewFileRouter(content) if e == nil { url := r.URL() routerURLSet.Add(&url) diff --git a/config/router_config_test.go b/config/router_config_test.go index 72e51c1c82..e4b09ef57d 100644 --- a/config/router_config_test.go +++ b/config/router_config_test.go @@ -31,6 +31,7 @@ import ( ) const testYML = "testdata/router_config.yml" +const testMultiRouterYML = "testdata/router_multi_config.yml" const errorTestYML = "testdata/router_config_error.yml" func TestString(t *testing.T) { @@ -63,4 +64,9 @@ func TestRouterInit(t *testing.T) { assert.NoError(t, errPro) assert.Equal(t, 1, routerURLSet.Size()) + + errPro = RouterInit(testMultiRouterYML) + assert.NoError(t, errPro) + + assert.Equal(t, 3, GetRouterURLSet().Size()) } diff --git a/config/service_config_test.go b/config/service_config_test.go index e7d55077be..a48cc6121a 100644 --- a/config/service_config_test.go +++ b/config/service_config_test.go @@ -153,7 +153,7 @@ func TestExport(t *testing.T) { providerConfig = nil } -func TestgetRandomPort(t *testing.T) { +func TestGetRandomPort(t *testing.T) { protocolConfigs := make([]*ProtocolConfig, 0, 3) ip, err := gxnet.GetLocalIP() diff --git a/config/testdata/router_config.yml b/config/testdata/router_config.yml index f6b91f5da7..1845650d93 100644 --- a/config/testdata/router_config.yml +++ b/config/testdata/router_config.yml @@ -1,6 +1,9 @@ # dubbo router yaml configure file -priority: 1 -force: true -conditions : - - "a => b" - - "c => d" \ No newline at end of file +routerRules: + - scope: application + key: mock-app + priority: 1 + force: true + conditions : + - "a => b" + - "c => d" \ No newline at end of file diff --git a/config/testdata/router_config_error.yml b/config/testdata/router_config_error.yml index 37894ac964..74e89cc52e 100644 --- a/config/testdata/router_config_error.yml +++ b/config/testdata/router_config_error.yml @@ -1,6 +1,7 @@ # dubbo router yaml configure file -priority: 1 -force: true -noConditions : - - "a => b" - - "c => d" \ No newline at end of file +routerRules: + - priority: 1 + force: true + noConditions : + - "a => b" + - "c => d" \ No newline at end of file diff --git a/config/testdata/router_multi_config.yml b/config/testdata/router_multi_config.yml new file mode 100644 index 0000000000..42bb4cbe70 --- /dev/null +++ b/config/testdata/router_multi_config.yml @@ -0,0 +1,16 @@ +# dubbo router yaml configure file +routerRules: + - scope: application + key: mock-app + priority: 1 + force: true + conditions : + - "a => b" + - "c => d" + - scope: application + key: mock-app2 + priority: 1 + force: true + conditions : + - "a => b" + - "c => d" \ No newline at end of file From a41c36eddaea0c76165ac102ec483cc3a93b39e3 Mon Sep 17 00:00:00 2001 From: william feng <> Date: Sun, 19 Jul 2020 00:15:39 +0800 Subject: [PATCH 03/10] format the change --- cluster/router/condition/router_rule.go | 4 +- cluster/router/condition/router_rule_test.go | 6 +- cluster/router/condition/router_test.go | 77 ++++++++++---------- common/constant/key.go | 4 +- config/router_config.go | 5 +- config/router_config_test.go | 4 +- 6 files changed, 51 insertions(+), 49 deletions(-) diff --git a/cluster/router/condition/router_rule.go b/cluster/router/condition/router_rule.go index f8c2c3ed0d..576dea87f9 100644 --- a/cluster/router/condition/router_rule.go +++ b/cluster/router/condition/router_rule.go @@ -26,9 +26,9 @@ import ( ) import ( - "github.com/apache/dubbo-go/common/constant" "github.com/apache/dubbo-go/cluster/router" "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" "github.com/apache/dubbo-go/common/yaml" ) @@ -58,7 +58,7 @@ func getRule(rawRule string) (*RouterRule, error) { return r, err } r.RawRule = rawRule - if len(r.Conditions) != 0 && r.Key != "" && (r.Scope == constant.RouterApplicationScope || r.Scope == constant.RouterServiceScope){ + if len(r.Conditions) != 0 && r.Key != "" && (r.Scope == constant.RouterApplicationScope || r.Scope == constant.RouterServiceScope) { r.Valid = true } diff --git a/cluster/router/condition/router_rule_test.go b/cluster/router/condition/router_rule_test.go index 1376058ed3..369b14f08a 100644 --- a/cluster/router/condition/router_rule_test.go +++ b/cluster/router/condition/router_rule_test.go @@ -73,9 +73,9 @@ key: test-provider conditions: - > method!=sayHello =>` - rule, e = getRule(testyml) - assert.Nil(t, e) - assert.False(t, rule.Valid) + rule, e = getRule(testyml) + assert.Nil(t, e) + assert.False(t, rule.Valid) } func TestIsMatchGlobPattern(t *testing.T) { diff --git a/cluster/router/condition/router_test.go b/cluster/router/condition/router_test.go index 151f6ccfca..35b8656b5f 100644 --- a/cluster/router/condition/router_test.go +++ b/cluster/router/condition/router_test.go @@ -15,46 +15,43 @@ * limitations under the License. */ - package condition +package condition - import ( - "testing" - ) - - import ( - "github.com/stretchr/testify/assert" - ) +import ( + "testing" +) - import ( +import ( "github.com/dubbogo/gost/container/set" - ) - - func TestParseRule(t *testing.T) { - testString := `` - matchPair, err := parseRule(testString) - assert.Nil(t, err) - assert.EqualValues(t, matchPair, make(map[string]MatchPair, 16)) - - testString = `method!=sayHello&application=sayGoodBye` - matchPair, err = parseRule(testString) - assert.Nil(t, err) - assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet("sayHello")) - assert.EqualValues(t, matchPair["application"].Matches, gxset.NewSet("sayGoodBye")) - - testString = `noRule` - matchPair, err = parseRule(testString) - assert.Nil(t, err) - assert.EqualValues(t, matchPair["noRule"].Mismatches, gxset.NewSet()) - assert.EqualValues(t, matchPair["noRule"].Matches, gxset.NewSet()) - - testString = `method!=sayHello,sayGoodBye` - matchPair, err = parseRule(testString) - assert.Nil(t, err) - assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet(`sayHello`, `sayGoodBye`)) - - testString = `method!=sayHello,sayGoodDay=sayGoodBye` - matchPair, err = parseRule(testString) - assert.Nil(t, err) - assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet(`sayHello`, `sayGoodDay`)) - assert.EqualValues(t, matchPair["method"].Matches, gxset.NewSet(`sayGoodBye`)) - } \ No newline at end of file + "github.com/stretchr/testify/assert" +) + +func TestParseRule(t *testing.T) { + testString := `` + matchPair, err := parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair, make(map[string]MatchPair, 16)) + + testString = `method!=sayHello&application=sayGoodBye` + matchPair, err = parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet("sayHello")) + assert.EqualValues(t, matchPair["application"].Matches, gxset.NewSet("sayGoodBye")) + + testString = `noRule` + matchPair, err = parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair["noRule"].Mismatches, gxset.NewSet()) + assert.EqualValues(t, matchPair["noRule"].Matches, gxset.NewSet()) + + testString = `method!=sayHello,sayGoodBye` + matchPair, err = parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet(`sayHello`, `sayGoodBye`)) + + testString = `method!=sayHello,sayGoodDay=sayGoodBye` + matchPair, err = parseRule(testString) + assert.Nil(t, err) + assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet(`sayHello`, `sayGoodDay`)) + assert.EqualValues(t, matchPair["method"].Matches, gxset.NewSet(`sayGoodBye`)) +} diff --git a/common/constant/key.go b/common/constant/key.go index 48d7a6dd10..f22debd58c 100644 --- a/common/constant/key.go +++ b/common/constant/key.go @@ -197,11 +197,11 @@ const ( // Priority Priority key in router module RouterPriority = "priority" // RouterScope Scope key in router module - RouterScope = "scope" + RouterScope = "scope" // RouterApplicationScope Scope key in router module RouterApplicationScope = "application" // RouterServiceScope Scope key in router module - RouterServiceScope = "service" + RouterServiceScope = "service" // RouterRuleKey defines the key of the router, service's/application's name RouterRuleKey = "key" // ForceUseTag is the tag in attachment diff --git a/config/router_config.go b/config/router_config.go index e9cd5dc749..ed42577ed3 100644 --- a/config/router_config.go +++ b/config/router_config.go @@ -33,9 +33,11 @@ var ( routerURLSet = gxset.NewSet() ) +// LocalRouterRules defines the local router config structure type LocalRouterRules struct { RouterRules []interface{} `yaml:"routerRules"` } + // RouterInit Load config file to init router config func RouterInit(confRouterFile string) error { bytes, err := yaml.LoadYMLConfig(confRouterFile) @@ -58,7 +60,7 @@ func RouterInit(confRouterFile string) error { return err } -func initRouterConfig (content []byte,factories map[string]router.FilePriorityRouterFactory) error { +func initRouterConfig(content []byte, factories map[string]router.FilePriorityRouterFactory) error { logger.Warnf("get fileRouterFactories len{%+v})", len(factories)) for k, factory := range factories { r, e := factory.NewFileRouter(content) @@ -72,6 +74,7 @@ func initRouterConfig (content []byte,factories map[string]router.FilePriorityRo return perrors.Errorf("no file router exists for parse %s , implement router.FIleRouterFactory please.", confRouterFile) } +// GetRouterURLSet exposes the routerURLSet func GetRouterURLSet() *gxset.HashSet { return routerURLSet } diff --git a/config/router_config_test.go b/config/router_config_test.go index e4b09ef57d..13af7056d5 100644 --- a/config/router_config_test.go +++ b/config/router_config_test.go @@ -23,6 +23,7 @@ import ( ) import ( + "github.com/dubbogo/gost/container/set" "github.com/stretchr/testify/assert" ) @@ -65,8 +66,9 @@ func TestRouterInit(t *testing.T) { assert.Equal(t, 1, routerURLSet.Size()) + routerURLSet = gxset.NewSet() errPro = RouterInit(testMultiRouterYML) assert.NoError(t, errPro) - assert.Equal(t, 3, GetRouterURLSet().Size()) + assert.Equal(t, 2, routerURLSet.Size()) } From b501734ad66ace709b5ce33b9e6dece9130e2b08 Mon Sep 17 00:00:00 2001 From: william feng <> Date: Sun, 19 Jul 2020 17:18:23 +0800 Subject: [PATCH 04/10] fix the test error --- cluster/router/chain/chain_test.go | 16 +++++++++++----- cluster/router/condition/app_router_test.go | 19 +++++++++++++------ cluster/router/condition/file_test.go | 10 +++++++--- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/cluster/router/chain/chain_test.go b/cluster/router/chain/chain_test.go index c1f723525f..065f0e49d9 100644 --- a/cluster/router/chain/chain_test.go +++ b/cluster/router/chain/chain_test.go @@ -66,7 +66,9 @@ func TestNewRouterChain(t *testing.T) { err = z.Create(path) assert.NoError(t, err) - testyml := `enabled: true + testyml := `scope: application +key: mock-app +enabled: true force: true runtime: false conditions: @@ -93,7 +95,7 @@ conditions: assert.NotNil(t, appRouter) assert.NotNil(t, appRouter.RouterRule()) rule := appRouter.RouterRule() - assert.Equal(t, "", rule.Scope) + assert.Equal(t, "application", rule.Scope) assert.True(t, rule.Force) assert.True(t, rule.Enabled) assert.True(t, rule.Valid) @@ -101,7 +103,7 @@ conditions: assert.Equal(t, testyml, rule.RawRule) assert.Equal(t, false, rule.Runtime) assert.Equal(t, false, rule.Dynamic) - assert.Equal(t, "", rule.Key) + assert.Equal(t, "mock-app", rule.Key) } func TestNewRouterChainURLNil(t *testing.T) { @@ -116,7 +118,9 @@ func TestRouterChainAddRouters(t *testing.T) { err = z.Create(path) assert.NoError(t, err) - testyml := `enabled: true + testyml := `scope: application +key: mock-app +enabled: true force: true runtime: false conditions: @@ -182,7 +186,9 @@ func TestRouterChainRouteAppRouter(t *testing.T) { err = z.Create(path) assert.NoError(t, err) - testyml := `enabled: true + testyml := `scope: application +key: mock-app +enabled: true force: true runtime: false conditions: diff --git a/cluster/router/condition/app_router_test.go b/cluster/router/condition/app_router_test.go index 8b38f2dd61..53465f9051 100644 --- a/cluster/router/condition/app_router_test.go +++ b/cluster/router/condition/app_router_test.go @@ -52,7 +52,9 @@ var ( func TestNewAppRouter(t *testing.T) { - testYML := `enabled: true + testYML := `scope: application +key: mock-app +enabled: true force: true runtime: false conditions: @@ -83,7 +85,7 @@ conditions: assert.NotNil(t, appRouter) assert.NotNil(t, appRouter.RouterRule()) rule := appRouter.RouterRule() - assert.Equal(t, "", rule.Scope) + assert.Equal(t, "application", rule.Scope) assert.True(t, rule.Force) assert.True(t, rule.Enabled) assert.True(t, rule.Valid) @@ -91,13 +93,15 @@ conditions: assert.Equal(t, testYML, rule.RawRule) assert.Equal(t, false, rule.Runtime) assert.Equal(t, false, rule.Dynamic) - assert.Equal(t, "", rule.Key) + assert.Equal(t, "mock-app", rule.Key) assert.Equal(t, 0, rule.Priority) } func TestGenerateConditions(t *testing.T) { - testYML := `enabled: true + testYML := `scope: application +key: mock-app +enabled: true force: true runtime: false conditions: @@ -135,7 +139,9 @@ conditions: func TestProcess(t *testing.T) { - testYML := `enabled: true + testYML := `scope: application +key: mock-app +enabled: true force: true runtime: false conditions: @@ -165,7 +171,8 @@ conditions: assert.Equal(t, 1, len(appRouter.conditionRouters)) - testNewYML := ` + testNewYML := `scope: application +key: mock-app enabled: true force: true runtime: false diff --git a/cluster/router/condition/file_test.go b/cluster/router/condition/file_test.go index 3092b12ff8..a568e08fa8 100644 --- a/cluster/router/condition/file_test.go +++ b/cluster/router/condition/file_test.go @@ -26,7 +26,9 @@ import ( ) func TestLoadYmlConfig(t *testing.T) { - router, e := NewFileConditionRouter([]byte(`priority: 1 + router, e := NewFileConditionRouter([]byte(`scope: application +key: mock-app +priority: 1 force: true conditions : - "a => b" @@ -47,12 +49,14 @@ func TestParseCondition(t *testing.T) { } func TestFileRouterURL(t *testing.T) { - router, e := NewFileConditionRouter([]byte(`priority: 1 + router, e := NewFileConditionRouter([]byte(`scope: application +key: mock-app +priority: 1 force: true conditions : - "a => b" - "c => d"`)) assert.Nil(t, e) assert.NotNil(t, router) - assert.Equal(t, "condition://0.0.0.0:?category=routers&force=true&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D", router.URL().String()) + assert.Equal(t, "condition://0.0.0.0:?category=routers&force=true&key=mock-app&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D&scope=application", router.URL().String()) } From b33167b117323d2697466dc35ef64395b9b2cf9d Mon Sep 17 00:00:00 2001 From: william feng <> Date: Mon, 27 Jul 2020 00:33:13 +0800 Subject: [PATCH 05/10] enable service level router configuration --- cluster/directory/base_directory.go | 38 +++++++++++--- cluster/directory/base_directory_test.go | 12 +++-- cluster/router/condition/file.go | 32 +++++++++++- cluster/router/condition/file_test.go | 66 +++++++++++++++++++++++- cluster/router/condition/router.go | 8 ++- cluster/router/condition/router_test.go | 31 +++++++++++ common/url.go | 2 +- 7 files changed, 173 insertions(+), 16 deletions(-) diff --git a/cluster/directory/base_directory.go b/cluster/directory/base_directory.go index 8a7e0c0e83..634cee4263 100644 --- a/cluster/directory/base_directory.go +++ b/cluster/directory/base_directory.go @@ -85,15 +85,21 @@ func (dir *BaseDirectory) SetRouters(urls []*common.URL) { for _, url := range urls { routerKey := url.GetParam(constant.ROUTER_KEY, "") - if len(routerKey) > 0 { - factory := extension.GetRouterFactory(url.Protocol) - r, err := factory.NewPriorityRouter(url) - if err != nil { - logger.Errorf("Create router fail. router key: %s, url:%s, error: %+v", routerKey, url.Service(), err) - return + if len(routerKey) == 0 { + continue + } + if url.Protocol == constant.CONDITION_ROUTE_PROTOCOL { + if !dir.isProperRouter(url) { + continue } - routers = append(routers, r) } + factory := extension.GetRouterFactory(url.Protocol) + r, err := factory.NewPriorityRouter(url) + if err != nil { + logger.Errorf("Create router fail. router key: %s, url:%s, error: %+v", routerKey, url.Service(), err) + return + } + routers = append(routers, r) } logger.Infof("Init file condition router success, size: %v", len(routers)) @@ -104,6 +110,24 @@ func (dir *BaseDirectory) SetRouters(urls []*common.URL) { rc.AddRouters(routers) } +func (dir *BaseDirectory) isProperRouter(url *common.URL) bool { + app := url.GetParam(constant.APPLICATION_KEY, "") + serviceKey := dir.GetUrl().ServiceKey() + if serviceKey == "" { + serviceKey = dir.GetUrl().SubURL.ServiceKey() + } + if len(app) > 0 { + if app != dir.GetUrl().GetParam(constant.APPLICATION_KEY, "") { + return false + } + } else { + if url.ServiceKey() != serviceKey { + return false + } + } + return true +} + // Destroy Destroy func (dir *BaseDirectory) Destroy(doDestroy func()) { if dir.destroyed.CAS(false, true) { diff --git a/cluster/directory/base_directory_test.go b/cluster/directory/base_directory_test.go index 8b60163b79..f60eddad79 100644 --- a/cluster/directory/base_directory_test.go +++ b/cluster/directory/base_directory_test.go @@ -48,13 +48,17 @@ func TestNewBaseDirectory(t *testing.T) { } func TestBuildRouterChain(t *testing.T) { - directory := NewBaseDirectory(&url) + + regURL := url + regURL.AddParam(constant.INTERFACE_KEY, "mock-app") + directory := NewBaseDirectory(®URL) assert.NotNil(t, directory) localIP, _ := gxnet.GetLocalIP() rule := base64.URLEncoding.EncodeToString([]byte("true => " + " host = " + localIP)) - routeURL := getRouteUrl(rule) + routeURL := getRouteURL(rule) + routeURL.AddParam(constant.INTERFACE_KEY, "mock-app") routerURLs := make([]*common.URL, 0) routerURLs = append(routerURLs, routeURL) directory.SetRouters(routerURLs) @@ -63,9 +67,9 @@ func TestBuildRouterChain(t *testing.T) { assert.NotNil(t, chain) } -func getRouteUrl(rule string) *common.URL { +func getRouteURL(rule string) *common.URL { anyUrl.AddParam("rule", rule) anyUrl.AddParam("force", "true") anyUrl.AddParam(constant.ROUTER_KEY, "router") - return &url + return &anyUrl } diff --git a/cluster/router/condition/file.go b/cluster/router/condition/file.go index 85658e7eb3..1eba3d6924 100644 --- a/cluster/router/condition/file.go +++ b/cluster/router/condition/file.go @@ -20,6 +20,7 @@ package condition import ( "encoding/base64" "net/url" + "regexp" "strconv" "strings" "sync" @@ -72,13 +73,40 @@ func (f *FileConditionRouter) URL() common.URL { common.WithParamsValue(constant.RULE_KEY, base64.URLEncoding.EncodeToString([]byte(rule))), common.WithParamsValue(constant.ROUTER_KEY, constant.CONDITION_ROUTE_PROTOCOL), common.WithParamsValue(constant.CATEGORY_KEY, constant.ROUTERS_CATEGORY), - common.WithParamsValue(constant.RouterRuleKey, routerRule.Key), - common.WithParamsValue(constant.RouterScope, routerRule.Scope), ) + if routerRule.Scope == constant.RouterApplicationScope { + f.url.AddParam(constant.APPLICATION_KEY, routerRule.Key) + } else { + grp, srv, ver, _ := parseServiceRouterKey(routerRule.Key) + if len(grp) > 0 { + f.url.AddParam(constant.GROUP_KEY, grp) + } + if len(ver) > 0 { + f.url.AddParam(constant.VERSION_KEY, ver) + } + if len(srv) > 0 { + f.url.AddParam(constant.INTERFACE_KEY, srv) + } + } }) return f.url } +func parseServiceRouterKey(key string) (string, string, string, error) { + if len(strings.TrimSpace(key)) == 0 { + return "", "", "", nil + } + reg := regexp.MustCompile(`(.*/{1})?([^:/]+)(:{1}[^:]*)?`) + strs := reg.FindAllStringSubmatch(key, -1) + if strs == nil || len(strs) != 1 { + return "", "", "", perrors.Errorf("Invalid key, service key must follow [{group}/]{service}[:{version}] pattern") + } + grp := strings.TrimSpace(strings.TrimRight(strs[0][1], "/")) + srv := strings.TrimSpace(strs[0][2]) + ver := strings.TrimSpace(strings.TrimLeft(strs[0][3], ":")) + return grp, srv, ver, nil +} + func parseCondition(conditions []string) string { var when, then string for _, condition := range conditions { diff --git a/cluster/router/condition/file_test.go b/cluster/router/condition/file_test.go index a568e08fa8..bd19a0d18c 100644 --- a/cluster/router/condition/file_test.go +++ b/cluster/router/condition/file_test.go @@ -58,5 +58,69 @@ conditions : - "c => d"`)) assert.Nil(t, e) assert.NotNil(t, router) - assert.Equal(t, "condition://0.0.0.0:?category=routers&force=true&key=mock-app&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D&scope=application", router.URL().String()) + assert.Equal(t, "condition://0.0.0.0:?application=mock-app&category=routers&force=true&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D", router.URL().String()) + + router, e = NewFileConditionRouter([]byte(`scope: service +key: mock-service +priority: 1 +force: true +conditions : + - "a => b" + - "c => d"`)) + assert.Nil(t, e) + assert.NotNil(t, router) + assert.Equal(t, "condition://0.0.0.0:?category=routers&force=true&interface=mock-service&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D", router.URL().String()) + + router, e = NewFileConditionRouter([]byte(`scope: service +key: grp1/mock-service:v1 +priority: 1 +force: true +conditions : + - "a => b" + - "c => d"`)) + assert.Nil(t, e) + assert.NotNil(t, router) + assert.Equal(t, "condition://0.0.0.0:?category=routers&force=true&group=grp1&interface=mock-service&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D&version=v1", router.URL().String()) +} + +func TestParseServiceRouterKey(t *testing.T) { + testString := " mock-group / mock-service:1.0.0" + grp, srv, ver, err := parseServiceRouterKey(testString) + assert.Equal(t, "mock-group", grp) + assert.Equal(t, "mock-service", srv) + assert.Equal(t, "1.0.0", ver) + + testString = "mock-group/mock-service" + grp, srv, ver, err = parseServiceRouterKey(testString) + assert.Equal(t, "mock-group", grp) + assert.Equal(t, "mock-service", srv) + assert.Equal(t, "", ver) + + testString = "mock-service:1.0.0" + grp, srv, ver, err = parseServiceRouterKey(testString) + assert.Equal(t, "", grp) + assert.Equal(t, "mock-service", srv) + assert.Equal(t, "1.0.0", ver) + + testString = "mock-service" + grp, srv, ver, err = parseServiceRouterKey(testString) + assert.Equal(t, "", grp) + assert.Equal(t, "mock-service", srv) + assert.Equal(t, "", ver) + + testString = "/mock-service:" + grp, srv, ver, err = parseServiceRouterKey(testString) + assert.Equal(t, "", grp) + assert.Equal(t, "mock-service", srv) + assert.Equal(t, "", ver) + + testString = "grp:mock-service:123" + grp, srv, ver, err = parseServiceRouterKey(testString) + assert.Error(t, err) + + testString = "" + grp, srv, ver, err = parseServiceRouterKey(testString) + assert.Equal(t, "", grp) + assert.Equal(t, "", srv) + assert.Equal(t, "", ver) } diff --git a/cluster/router/condition/router.go b/cluster/router/condition/router.go index 40a251573f..8940805061 100644 --- a/cluster/router/condition/router.go +++ b/cluster/router/condition/router.go @@ -117,7 +117,13 @@ func NewConditionRouter(url *common.URL) (*ConditionRouter, error) { } router.url = url - router.priority = url.GetParamInt(constant.RouterPriority, 0) + var defaultPriority int64 + if url.GetParam(constant.APPLICATION_KEY, "") != "" { + defaultPriority = 150 + } else { + defaultPriority = 140 + } + router.priority = url.GetParamInt(constant.RouterPriority, defaultPriority) router.Force = url.GetParamBool(constant.RouterForce, false) router.enabled = url.GetParamBool(constant.RouterEnabled, true) diff --git a/cluster/router/condition/router_test.go b/cluster/router/condition/router_test.go index 35b8656b5f..c27a1d9552 100644 --- a/cluster/router/condition/router_test.go +++ b/cluster/router/condition/router_test.go @@ -22,6 +22,7 @@ import ( ) import ( + "github.com/apache/dubbo-go/common" "github.com/dubbogo/gost/container/set" "github.com/stretchr/testify/assert" ) @@ -55,3 +56,33 @@ func TestParseRule(t *testing.T) { assert.EqualValues(t, matchPair["method"].Mismatches, gxset.NewSet(`sayHello`, `sayGoodDay`)) assert.EqualValues(t, matchPair["method"].Matches, gxset.NewSet(`sayGoodBye`)) } + +func TestNewConditionRouter(t *testing.T) { + url, _ := common.NewURL(`condition://0.0.0.0:?application=mock-app&category=routers&force=true&priority=1&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D`) + router, err := NewConditionRouter(&url) + assert.Nil(t, err) + assert.Equal(t, true, router.Enabled()) + assert.Equal(t, true, router.Force) + assert.Equal(t, int64(1), router.Priority()) + whenRule, _ := parseRule("a & c") + thenRule, _ := parseRule("b & d") + assert.EqualValues(t, router.WhenCondition, whenRule) + assert.EqualValues(t, router.ThenCondition, thenRule) + + router, err = NewConditionRouter(nil) + assert.Error(t, err) + + url, _ = common.NewURL(`condition://0.0.0.0:?application=mock-app&category=routers&force=true&priority=1&router=condition&rule=YSAmT4gYiAmIGQ%3D`) + router, err = NewConditionRouter(&url) + assert.Error(t, err) + + url, _ = common.NewURL(`condition://0.0.0.0:?application=mock-app&category=routers&force=true&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D`) + router, err = NewConditionRouter(&url) + assert.Nil(t, err) + assert.Equal(t, int64(150), router.Priority()) + + url, _ = common.NewURL(`condition://0.0.0.0:?category=routers&force=true&interface=mock-service&router=condition&rule=YSAmIGMgPT4gYiAmIGQ%3D`) + router, err = NewConditionRouter(&url) + assert.Nil(t, err) + assert.Equal(t, int64(140), router.Priority()) +} diff --git a/common/url.go b/common/url.go index 807d0ed5ef..ec6dce9175 100644 --- a/common/url.go +++ b/common/url.go @@ -381,7 +381,7 @@ func (c URL) Service() string { if service != "" { return service } else if c.SubURL != nil { - service = c.GetParam(constant.INTERFACE_KEY, strings.TrimPrefix(c.Path, "/")) + service = c.SubURL.GetParam(constant.INTERFACE_KEY, strings.TrimPrefix(c.Path, "/")) if service != "" { // if url.path is "" then return suburl's path, special for registry url return service } From 740be76f4e2648ace14da1d18d2ff5335cc76885 Mon Sep 17 00:00:00 2001 From: william feng <> Date: Tue, 28 Jul 2020 12:39:53 +0800 Subject: [PATCH 06/10] resolve comment from zouyx --- cluster/router/condition/file.go | 30 +++++++++++++++---------- cluster/router/condition/router_rule.go | 2 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/cluster/router/condition/file.go b/cluster/router/condition/file.go index 1eba3d6924..d4293c9809 100644 --- a/cluster/router/condition/file.go +++ b/cluster/router/condition/file.go @@ -76,17 +76,20 @@ func (f *FileConditionRouter) URL() common.URL { ) if routerRule.Scope == constant.RouterApplicationScope { f.url.AddParam(constant.APPLICATION_KEY, routerRule.Key) - } else { - grp, srv, ver, _ := parseServiceRouterKey(routerRule.Key) - if len(grp) > 0 { - f.url.AddParam(constant.GROUP_KEY, grp) - } - if len(ver) > 0 { - f.url.AddParam(constant.VERSION_KEY, ver) - } - if len(srv) > 0 { - f.url.AddParam(constant.INTERFACE_KEY, srv) - } + return + } + grp, srv, ver, e := parseServiceRouterKey(routerRule.Key) + if e != nil { + return + } + if len(grp) > 0 { + f.url.AddParam(constant.GROUP_KEY, grp) + } + if len(ver) > 0 { + f.url.AddParam(constant.VERSION_KEY, ver) + } + if len(srv) > 0 { + f.url.AddParam(constant.INTERFACE_KEY, srv) } }) return f.url @@ -98,9 +101,12 @@ func parseServiceRouterKey(key string) (string, string, string, error) { } reg := regexp.MustCompile(`(.*/{1})?([^:/]+)(:{1}[^:]*)?`) strs := reg.FindAllStringSubmatch(key, -1) - if strs == nil || len(strs) != 1 { + if strs == nil || len(strs) > 1 { return "", "", "", perrors.Errorf("Invalid key, service key must follow [{group}/]{service}[:{version}] pattern") } + if len(strs[0]) != 4 { + return "", "", "", perrors.Errorf("Parse service router key failed") + } grp := strings.TrimSpace(strings.TrimRight(strs[0][1], "/")) srv := strings.TrimSpace(strs[0][2]) ver := strings.TrimSpace(strings.TrimLeft(strs[0][3], ":")) diff --git a/cluster/router/condition/router_rule.go b/cluster/router/condition/router_rule.go index 576dea87f9..9f2bf2d41a 100644 --- a/cluster/router/condition/router_rule.go +++ b/cluster/router/condition/router_rule.go @@ -58,7 +58,7 @@ func getRule(rawRule string) (*RouterRule, error) { return r, err } r.RawRule = rawRule - if len(r.Conditions) != 0 && r.Key != "" && (r.Scope == constant.RouterApplicationScope || r.Scope == constant.RouterServiceScope) { + if len(r.Conditions) > 0 && len(r.Key) > 0 && (r.Scope == constant.RouterApplicationScope || r.Scope == constant.RouterServiceScope) { r.Valid = true } From 95e863e570667b29d9c85e5f544abff1b183729a Mon Sep 17 00:00:00 2001 From: william feng <> Date: Fri, 7 Aug 2020 16:37:26 +0800 Subject: [PATCH 07/10] add default priority 0 for condition url which neither application nor service level router --- cluster/router/condition/router.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cluster/router/condition/router.go b/cluster/router/condition/router.go index 8940805061..6be3a4fc0a 100644 --- a/cluster/router/condition/router.go +++ b/cluster/router/condition/router.go @@ -120,8 +120,10 @@ func NewConditionRouter(url *common.URL) (*ConditionRouter, error) { var defaultPriority int64 if url.GetParam(constant.APPLICATION_KEY, "") != "" { defaultPriority = 150 - } else { + } else if url.GetParam(constant.INTERFACE_KEY, "") != "" { defaultPriority = 140 + } else { + defaultPriority = 0 } router.priority = url.GetParamInt(constant.RouterPriority, defaultPriority) router.Force = url.GetParamBool(constant.RouterForce, false) From 01910a00960fe6f1166d5fd67593791615e4fa1e Mon Sep 17 00:00:00 2001 From: william feng <> Date: Fri, 7 Aug 2020 16:45:36 +0800 Subject: [PATCH 08/10] reduce cognitive in base_directory.go --- cluster/directory/base_directory.go | 13 +++++-------- cluster/router/condition/router.go | 4 +--- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/cluster/directory/base_directory.go b/cluster/directory/base_directory.go index 634cee4263..7e1563a831 100644 --- a/cluster/directory/base_directory.go +++ b/cluster/directory/base_directory.go @@ -116,14 +116,11 @@ func (dir *BaseDirectory) isProperRouter(url *common.URL) bool { if serviceKey == "" { serviceKey = dir.GetUrl().SubURL.ServiceKey() } - if len(app) > 0 { - if app != dir.GetUrl().GetParam(constant.APPLICATION_KEY, "") { - return false - } - } else { - if url.ServiceKey() != serviceKey { - return false - } + if len(app) > 0 && app != dir.GetUrl().GetParam(constant.APPLICATION_KEY, "") { + return false + } + if url.ServiceKey() != serviceKey { + return false } return true } diff --git a/cluster/router/condition/router.go b/cluster/router/condition/router.go index 6be3a4fc0a..800293da6c 100644 --- a/cluster/router/condition/router.go +++ b/cluster/router/condition/router.go @@ -117,13 +117,11 @@ func NewConditionRouter(url *common.URL) (*ConditionRouter, error) { } router.url = url - var defaultPriority int64 + var defaultPriority int64 = 0 if url.GetParam(constant.APPLICATION_KEY, "") != "" { defaultPriority = 150 } else if url.GetParam(constant.INTERFACE_KEY, "") != "" { defaultPriority = 140 - } else { - defaultPriority = 0 } router.priority = url.GetParamInt(constant.RouterPriority, defaultPriority) router.Force = url.GetParamBool(constant.RouterForce, false) From 96a368819bac04072cd315179381e550fcdb8ee5 Mon Sep 17 00:00:00 2001 From: william feng <> Date: Sat, 8 Aug 2020 16:57:20 +0800 Subject: [PATCH 09/10] fix empty application configure always return true in base_directory setup --- cluster/directory/base_directory.go | 10 ++-- cluster/directory/base_directory_test.go | 58 +++++++++++++++++++++--- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/cluster/directory/base_directory.go b/cluster/directory/base_directory.go index 7e1563a831..651c90ff68 100644 --- a/cluster/directory/base_directory.go +++ b/cluster/directory/base_directory.go @@ -116,13 +116,13 @@ func (dir *BaseDirectory) isProperRouter(url *common.URL) bool { if serviceKey == "" { serviceKey = dir.GetUrl().SubURL.ServiceKey() } - if len(app) > 0 && app != dir.GetUrl().GetParam(constant.APPLICATION_KEY, "") { - return false + if len(app) > 0 && app == dir.GetUrl().GetParam(constant.APPLICATION_KEY, "") { + return true } - if url.ServiceKey() != serviceKey { - return false + if url.ServiceKey() == serviceKey { + return true } - return true + return false } // Destroy Destroy diff --git a/cluster/directory/base_directory_test.go b/cluster/directory/base_directory_test.go index f60eddad79..a2b62dfa00 100644 --- a/cluster/directory/base_directory_test.go +++ b/cluster/directory/base_directory_test.go @@ -37,7 +37,7 @@ import ( var ( url, _ = common.NewURL( fmt.Sprintf("dubbo://%s:%d/com.ikurento.user.UserProvider", constant.LOCAL_HOST_VALUE, constant.DEFAULT_PORT)) - anyUrl, _ = common.NewURL(fmt.Sprintf("condition://%s/com.foo.BarService", constant.ANYHOST_VALUE)) + anyURL, _ = common.NewURL(fmt.Sprintf("condition://%s/com.foo.BarService", constant.ANYHOST_VALUE)) ) func TestNewBaseDirectory(t *testing.T) { @@ -57,7 +57,7 @@ func TestBuildRouterChain(t *testing.T) { localIP, _ := gxnet.GetLocalIP() rule := base64.URLEncoding.EncodeToString([]byte("true => " + " host = " + localIP)) - routeURL := getRouteURL(rule) + routeURL := getRouteURL(rule, anyURL) routeURL.AddParam(constant.INTERFACE_KEY, "mock-app") routerURLs := make([]*common.URL, 0) routerURLs = append(routerURLs, routeURL) @@ -67,9 +67,53 @@ func TestBuildRouterChain(t *testing.T) { assert.NotNil(t, chain) } -func getRouteURL(rule string) *common.URL { - anyUrl.AddParam("rule", rule) - anyUrl.AddParam("force", "true") - anyUrl.AddParam(constant.ROUTER_KEY, "router") - return &anyUrl +func getRouteURL(rule string, u common.URL) *common.URL { + ru := u + ru.AddParam("rule", rule) + ru.AddParam("force", "true") + ru.AddParam(constant.ROUTER_KEY, "router") + return &ru +} + +func TestIsProperRouter(t *testing.T) { + regURL := url + regURL.AddParam(constant.APPLICATION_KEY, "mock-app") + d := NewBaseDirectory(®URL) + localIP, _ := gxnet.GetLocalIP() + rule := base64.URLEncoding.EncodeToString([]byte("true => " + " host = " + localIP)) + routeURL := getRouteURL(rule, anyURL) + routeURL.AddParam(constant.APPLICATION_KEY, "mock-app") + rst := d.isProperRouter(routeURL) + assert.True(t, rst) + + regURL.AddParam(constant.APPLICATION_KEY, "") + regURL.AddParam(constant.INTERFACE_KEY, "com.foo.BarService") + d = NewBaseDirectory(®URL) + routeURL = getRouteURL(rule, anyURL) + routeURL.AddParam(constant.INTERFACE_KEY, "com.foo.BarService") + rst = d.isProperRouter(routeURL) + assert.True(t, rst) + + regURL.AddParam(constant.APPLICATION_KEY, "") + regURL.AddParam(constant.INTERFACE_KEY, "") + d = NewBaseDirectory(®URL) + routeURL = getRouteURL(rule, anyURL) + rst = d.isProperRouter(routeURL) + assert.True(t, rst) + + regURL.SetParam(constant.APPLICATION_KEY, "") + regURL.SetParam(constant.INTERFACE_KEY, "") + d = NewBaseDirectory(®URL) + routeURL = getRouteURL(rule, anyURL) + routeURL.AddParam(constant.APPLICATION_KEY, "mock-service") + rst = d.isProperRouter(routeURL) + assert.False(t, rst) + + regURL.SetParam(constant.APPLICATION_KEY, "") + regURL.SetParam(constant.INTERFACE_KEY, "") + d = NewBaseDirectory(®URL) + routeURL = getRouteURL(rule, anyURL) + routeURL.AddParam(constant.INTERFACE_KEY, "mock-service") + rst = d.isProperRouter(routeURL) + assert.False(t, rst) } From 5f02d5372ee87df8904e5b55925923fbf656b8a2 Mon Sep 17 00:00:00 2001 From: william feng <> Date: Sat, 8 Aug 2020 17:03:34 +0800 Subject: [PATCH 10/10] added comment to file.go --- cluster/router/condition/file.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cluster/router/condition/file.go b/cluster/router/condition/file.go index d4293c9809..996db7443f 100644 --- a/cluster/router/condition/file.go +++ b/cluster/router/condition/file.go @@ -95,6 +95,12 @@ func (f *FileConditionRouter) URL() common.URL { return f.url } +// The input value must follow [{group}/]{service}[:{version}] pattern +// the returning strings are representing group, service, version respectively. +// input: mock-group/mock-service:1.0.0 ==> "mock-group", "mock-service", "1.0.0" +// input: mock-group/mock-service ==> "mock-group", "mock-service", "" +// input: mock-service:1.0.0 ==> "", "mock-service", "1.0.0" +// For more samples, please refer to unit test. func parseServiceRouterKey(key string) (string, string, string, error) { if len(strings.TrimSpace(key)) == 0 { return "", "", "", nil