Skip to content

Commit

Permalink
satellite/nodeselection: support OR in placement definition
Browse files Browse the repository at this point in the history
Change-Id: Icc7fd465b28c0c6f09f50c4ab8bffbcc77631dbd
  • Loading branch information
elek authored and Storj Robot committed Oct 19, 2023
1 parent 3e71ea5 commit a63a69d
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
27 changes: 26 additions & 1 deletion satellite/nodeselection/filter.go
Expand Up @@ -132,6 +132,27 @@ func (n NodeFilters) Match(node *SelectedNode) bool {
return true
}

// OrFilter will include the node, if at lest one of the filters are matched.
type OrFilter []NodeFilter

// Match implements NodeFilter interface.
func (n OrFilter) Match(node *SelectedNode) bool {
for _, filter := range n {
if filter.Match(node) {
return true
}
}
return false
}

func (n OrFilter) String() string {
var parts []string
for _, filter := range n {
parts = append(parts, fmt.Sprintf("%s", filter))
}
return "(" + strings.Join(parts, " || ") + ")"
}

// WithCountryFilter is a helper to create a new filter with additional CountryFilter.
func (n NodeFilters) WithCountryFilter(permit location.Set) NodeFilters {
return append(n, NewCountryFilter(permit))
Expand All @@ -143,12 +164,16 @@ func (n NodeFilters) WithExcludedIDs(ds []storj.NodeID) NodeFilters {
}

func (n NodeFilters) String() string {
if len(n) == 1 {
return fmt.Sprintf("%s", n[0])
}

var res []string
for _, filter := range n {
res = append(res, fmt.Sprintf("%s", filter))
}
sort.Strings(res)
return strings.Join(res, " && ")
return "(" + strings.Join(res, " && ") + ")"
}

// GetAnnotation implements NodeFilterWithAnnotation.
Expand Down
8 changes: 8 additions & 0 deletions satellite/overlay/placement.go
Expand Up @@ -121,6 +121,14 @@ func (d *PlacementDefinitions) AddPlacementFromString(definitions string) error
res := nodeselection.NodeFilters{filter1, filter2}
return res, nil
},
mito.OpOr: func(env map[any]any, a, b any) (any, error) {
filter1, ok1 := a.(nodeselection.NodeFilter)
filter2, ok2 := b.(nodeselection.NodeFilter)
if !ok1 || !ok2 {
return nil, errs.New("OR is supported only between NodeFilter instances")
}
return nodeselection.OrFilter{filter1, filter2}, nil
},
"tag": func(nodeIDstr string, key string, value any) (nodeselection.NodeFilters, error) {
nodeID, err := storj.NodeIDFromString(nodeIDstr)
if err != nil {
Expand Down
48 changes: 48 additions & 0 deletions satellite/overlay/placement_test.go
Expand Up @@ -248,6 +248,54 @@ func TestPlacementFromString(t *testing.T) {

})

t.Run("OR", func(t *testing.T) {
p := NewPlacementDefinitions()
err := p.AddPlacementFromString(`11:country("GB") || country("DE")`)
require.NoError(t, err)

filters := p.placements[storj.PlacementConstraint(11)]
require.NotNil(t, filters)
require.True(t, filters.Match(&nodeselection.SelectedNode{
CountryCode: location.UnitedKingdom,
}))
require.True(t, filters.Match(&nodeselection.SelectedNode{
CountryCode: location.Germany,
}))
require.Equal(t, `(country("GB") || country("DE"))`, fmt.Sprintf("%s", filters))
})

t.Run("OR combined with AND", func(t *testing.T) {
p := NewPlacementDefinitions()
err := p.AddPlacementFromString(`11:((country("GB") || country("DE")) && tag("12whfK1EDvHJtajBiAUeajQLYcWqxcQmdYQU5zX5cCf6bAxfgu4","foo","bar"))`)
require.NoError(t, err)

filters := p.placements[storj.PlacementConstraint(11)]
require.NotNil(t, filters)
require.False(t, filters.Match(&nodeselection.SelectedNode{
CountryCode: location.UnitedKingdom,
}))
require.False(t, filters.Match(&nodeselection.SelectedNode{
Tags: nodeselection.NodeTags{
{
Signer: signer,
Name: "foo",
Value: []byte("bar"),
},
},
}))
require.True(t, filters.Match(&nodeselection.SelectedNode{
CountryCode: location.Germany,
Tags: nodeselection.NodeTags{
{
Signer: signer,
Name: "foo",
Value: []byte("bar"),
},
},
}))
require.Equal(t, `((country("GB") || country("DE")) && tag("12whfK1EDvHJtajBiAUeajQLYcWqxcQmdYQU5zX5cCf6bAxfgu4","foo","bar"))`, fmt.Sprintf("%s", filters))
})

t.Run("annotation usage", func(t *testing.T) {
t.Run("normal", func(t *testing.T) {
t.Parallel()
Expand Down

0 comments on commit a63a69d

Please sign in to comment.