diff --git a/manager/searcher/searcher.go b/manager/searcher/searcher.go index c7b59dab3..a4e0cd2cb 100644 --- a/manager/searcher/searcher.go +++ b/manager/searcher/searcher.go @@ -139,6 +139,7 @@ func (s *searcher) FindSchedulerCluster(ctx context.Context, schedulerClusters [ for _, cluster := range clusters { var scopes Scopes if err := mapstructure.Decode(cluster.Scopes, &scopes); err != nil { + logger.Infof("cluster %s decode scopes failed: %v", cluster.Name, err) // Scopes parse failed to skip this evaluation continue } @@ -162,10 +163,24 @@ func Evaluate(conditions map[string]string, scopes Scopes) float64 { // calculateIDCAffinityScore 0.0~1.0 larger and better func calculateIDCAffinityScore(dst, src string) float64 { - if dst != "" && src != "" && strings.Compare(dst, src) == 0 { + if dst == "" || src == "" { + return minScore + } + + if strings.Compare(dst, src) == 0 { return maxScore } + // Dst has only one element, src has multiple elements separated by "|". + // When dst element matches one of the multiple elements of src, + // it gets the max score of idc. + srcElements := strings.Split(src, "|") + for _, srcElement := range srcElements { + if strings.Compare(dst, srcElement) == 0 { + return maxScore + } + } + return minScore } diff --git a/manager/searcher/searcher_test.go b/manager/searcher/searcher_test.go index 2e02b2f06..34af2c377 100644 --- a/manager/searcher/searcher_test.go +++ b/manager/searcher/searcher_test.go @@ -117,7 +117,7 @@ func TestSchedulerCluster(t *testing.T) { { Name: "foo", Scopes: map[string]interface{}{ - "location": []string{"location-1"}, + "location": "location-1", }, Schedulers: []model.Scheduler{ { @@ -149,7 +149,7 @@ func TestSchedulerCluster(t *testing.T) { { Name: "foo", Scopes: map[string]interface{}{ - "idc": []string{"idc-1"}, + "idc": "idc|idc-1", }, Schedulers: []model.Scheduler{ { @@ -160,6 +160,9 @@ func TestSchedulerCluster(t *testing.T) { }, { Name: "bar", + Scopes: map[string]interface{}{ + "idc": "idc-2|idc-3", + }, Schedulers: []model.Scheduler{ { HostName: "bar", @@ -168,10 +171,10 @@ func TestSchedulerCluster(t *testing.T) { }, }, }, - conditions: map[string]string{"idc": "idc-1"}, + conditions: map[string]string{"idc": "idc-2"}, expect: func(t *testing.T, data model.SchedulerCluster, err error) { assert := assert.New(t) - assert.Equal(data.Name, "foo") + assert.Equal(data.Name, "bar") assert.NoError(err) }, }, @@ -181,7 +184,7 @@ func TestSchedulerCluster(t *testing.T) { { Name: "foo", Scopes: map[string]interface{}{ - "net_topology": []string{"net-topology-1"}, + "net_topology": "net-topology-1", }, Schedulers: []model.Scheduler{ { @@ -213,8 +216,8 @@ func TestSchedulerCluster(t *testing.T) { { Name: "foo", Scopes: map[string]interface{}{ - "location": []string{"location-1"}, - "idc": []string{"idc-1"}, + "location": "location-1|location-2", + "idc": "idc-1|idc-2", }, Schedulers: []model.Scheduler{ { @@ -249,7 +252,7 @@ func TestSchedulerCluster(t *testing.T) { { Name: "foo", Scopes: map[string]interface{}{ - "location": []string{"location-1"}, + "location": "location-1", }, SecurityGroup: model.SecurityGroup{ SecurityRules: []model.SecurityRule{ @@ -291,7 +294,7 @@ func TestSchedulerCluster(t *testing.T) { { Name: "foo", Scopes: map[string]interface{}{ - "idc": []string{"idc-1"}, + "idc": "idc-1", }, SecurityGroup: model.SecurityGroup{ SecurityRules: []model.SecurityRule{ @@ -328,13 +331,13 @@ func TestSchedulerCluster(t *testing.T) { }, }, { - name: "match according to all conditions", + name: "match according to security_domain, idc and location conditions", schedulerClusters: []model.SchedulerCluster{ { Name: "foo", Scopes: map[string]interface{}{ - "idc": []string{"idc-1"}, - "location": []string{"location-1"}, + "idc": "idc-1", + "location": "location-1", }, SecurityGroup: model.SecurityGroup{ SecurityRules: []model.SecurityRule{ @@ -352,6 +355,17 @@ func TestSchedulerCluster(t *testing.T) { }, { Name: "bar", + Scopes: map[string]interface{}{ + "idc": "idc-2", + "location": "location-1", + }, + SecurityGroup: model.SecurityGroup{ + SecurityRules: []model.SecurityRule{ + { + Domain: "domain-1", + }, + }, + }, Schedulers: []model.Scheduler{ { HostName: "bar", @@ -362,8 +376,8 @@ func TestSchedulerCluster(t *testing.T) { }, conditions: map[string]string{ "security_domain": "domain-1", - "idc": "idc-1", - "location": "location-1", + "idc": "idc-1|idc-2", + "location": "location-1|location-2", }, expect: func(t *testing.T, data model.SchedulerCluster, err error) { assert := assert.New(t) @@ -371,6 +385,61 @@ func TestSchedulerCluster(t *testing.T) { assert.NoError(err) }, }, + { + name: "match according to all conditions", + schedulerClusters: []model.SchedulerCluster{ + { + Name: "foo", + Scopes: map[string]interface{}{ + "idc": "idc-1", + "location": "location-2", + }, + SecurityGroup: model.SecurityGroup{ + SecurityRules: []model.SecurityRule{ + { + Domain: "domain-1", + }, + }, + }, + Schedulers: []model.Scheduler{ + { + HostName: "foo", + State: "active", + }, + }, + }, + { + Name: "bar", + Scopes: map[string]interface{}{ + "idc": "idc-1", + "location": "location-1", + }, + SecurityGroup: model.SecurityGroup{ + SecurityRules: []model.SecurityRule{ + { + Domain: "domain-1", + }, + }, + }, + Schedulers: []model.Scheduler{ + { + HostName: "bar", + State: "active", + }, + }, + }, + }, + conditions: map[string]string{ + "security_domain": "domain-1", + "idc": "idc-1|idc-2", + "location": "location-1|location-2", + }, + expect: func(t *testing.T, data model.SchedulerCluster, err error) { + assert := assert.New(t) + assert.Equal(data.Name, "bar") + assert.NoError(err) + }, + }, } for _, tc := range tests {