From f7da6ba99cc2c1d49f5082980ca236f51a8b126b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 5 Dec 2024 15:30:53 +0300 Subject: [PATCH] [#306] netmap: Allow to select empty set of nodes Signed-off-by: Evgenii Stratonikov --- netmap/selector.go | 2 +- netmap/selector_test.go | 33 +++++++++++++++++++++ netmap/yml_test.go | 11 +++++-- netmap/yml_tests/filter_complex.yml | 3 -- netmap/yml_tests/filter_invalid_integer.yml | 2 -- netmap/yml_tests/filter_simple.yml | 6 ---- netmap/yml_tests/selector_invalid.yml | 1 - 7 files changed, 43 insertions(+), 15 deletions(-) diff --git a/netmap/selector.go b/netmap/selector.go index 3e8adad..d6ea4cd 100644 --- a/netmap/selector.go +++ b/netmap/selector.go @@ -114,7 +114,7 @@ func (c *context) getSelection(s netmap.Selector) ([]nodes, error) { } if len(res) < bucketCount { - if len(res) == 0 { + if c.strict && len(res) == 0 { return nil, errNotEnoughNodes } bucketCount = len(res) diff --git a/netmap/selector_test.go b/netmap/selector_test.go index 538b845..ae996dd 100644 --- a/netmap/selector_test.go +++ b/netmap/selector_test.go @@ -254,6 +254,39 @@ func TestPlacementPolicy_ProcessSelectors(t *testing.T) { } } +func TestPlacementPolicy_PartiallyMissingContainer(t *testing.T) { + s := `REP 2 IN D1OBJ +REP 2 IN D2OBJ +CBF 2 +SELECT 2 FROM PRIMARY AS D1OBJ +SELECT 2 FROM SECONDARY AS D2OBJ +FILTER ClusterName EQ D1OBJ AS PRIMARY +FILTER ClusterName EQ D2OBJ AS SECONDARY` + + var p PlacementPolicy + require.NoError(t, p.DecodeString(s)) + + nodes := []NodeInfo{ + nodeInfoFromAttributes("ClusterName", "D1OBJ", "ID", "1"), + nodeInfoFromAttributes("ClusterName", "D1OBJ", "ID", "2"), + nodeInfoFromAttributes("ClusterName", "D1OBJ", "ID", "3"), + nodeInfoFromAttributes("ClusterName", "D1OBJ", "ID", "4"), + nodeInfoFromAttributes("ClusterName", "D1OBJ", "ID", "5"), + nodeInfoFromAttributes("ClusterName", "D1OBJ", "ID", "6"), + nodeInfoFromAttributes("ClusterName", "D1OBJ", "ID", "7"), + nodeInfoFromAttributes("ClusterName", "D1OBJ", "ID", "8"), + } + + var nm NetMap + nm.SetNodes(nodes) + + res, err := nm.ContainerNodes(p, nil) + require.NoError(t, err) + require.Len(t, res, 2) + require.Len(t, res[0], 4) + require.Len(t, res[1], 0) +} + func TestPlacementPolicy_Like(t *testing.T) { nodes := []NodeInfo{ nodeInfoFromAttributes("Country", "Russia"), diff --git a/netmap/yml_test.go b/netmap/yml_test.go index 4df6e0a..1f83462 100644 --- a/netmap/yml_test.go +++ b/netmap/yml_test.go @@ -84,8 +84,15 @@ func TestPlacementPolicy_Interopability(t *testing.T) { t.Run(name, func(t *testing.T) { v, err := nm.ContainerNodes(tt.Policy, tt.Pivot) if tt.Result == nil { - require.Error(t, err) - require.Contains(t, err.Error(), tt.Error) + if tt.Error != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tt.Error) + } else { + require.Len(t, v, tt.Policy.NumberOfReplicas()) + for i := range v { + require.Len(t, v[i], 0) + } + } } else { require.NoError(t, err) require.Equal(t, srcNodes, tc.Nodes) diff --git a/netmap/yml_tests/filter_complex.yml b/netmap/yml_tests/filter_complex.yml index a65fa17..1abc46a 100644 --- a/netmap/yml_tests/filter_complex.yml +++ b/netmap/yml_tests/filter_complex.yml @@ -107,7 +107,6 @@ tests: op: EQ value: Value2 filters: [] - error: not enough nodes bad rating: policy: replicas: @@ -157,7 +156,6 @@ tests: op: EQ value: Value2 filters: [] - error: not enough nodes bad param: policy: replicas: @@ -207,4 +205,3 @@ tests: op: EQ value: Value2 filters: [] - error: not enough nodes diff --git a/netmap/yml_tests/filter_invalid_integer.yml b/netmap/yml_tests/filter_invalid_integer.yml index e65ab24..6674246 100644 --- a/netmap/yml_tests/filter_invalid_integer.yml +++ b/netmap/yml_tests/filter_invalid_integer.yml @@ -24,7 +24,6 @@ tests: op: LE value: '8' filters: [] - error: not enough nodes non-empty string is not casted to a number: policy: replicas: @@ -42,4 +41,3 @@ tests: op: GE value: '0' filters: [] - error: not enough nodes diff --git a/netmap/yml_tests/filter_simple.yml b/netmap/yml_tests/filter_simple.yml index a24814a..7fdd84a 100644 --- a/netmap/yml_tests/filter_simple.yml +++ b/netmap/yml_tests/filter_simple.yml @@ -42,7 +42,6 @@ tests: op: GE value: '5' filters: [] - error: not enough nodes GT true: policy: replicas: @@ -79,7 +78,6 @@ tests: op: GT value: '4' filters: [] - error: not enough nodes LE true: policy: replicas: @@ -116,7 +114,6 @@ tests: op: LE value: '3' filters: [] - error: not enough nodes LT true: policy: replicas: @@ -153,7 +150,6 @@ tests: op: LT value: '4' filters: [] - error: not enough nodes EQ true: policy: replicas: @@ -190,7 +186,6 @@ tests: op: EQ value: China filters: [] - error: not enough nodes NE true: policy: replicas: @@ -227,4 +222,3 @@ tests: op: NE value: Germany filters: [] - error: not enough nodes diff --git a/netmap/yml_tests/selector_invalid.yml b/netmap/yml_tests/selector_invalid.yml index d6e3b4e..9b0a539 100644 --- a/netmap/yml_tests/selector_invalid.yml +++ b/netmap/yml_tests/selector_invalid.yml @@ -45,4 +45,3 @@ tests: op: EQ value: Moon filters: [] - error: not enough nodes