2023-06-30 11:13:18 +01:00
|
|
|
// Copyright (C) 2023 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package overlay
|
|
|
|
|
|
|
|
import (
|
2023-09-14 17:42:59 +01:00
|
|
|
"bytes"
|
2023-09-25 13:49:32 +01:00
|
|
|
"os"
|
2023-07-06 13:35:26 +01:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/jtolio/mito"
|
|
|
|
"github.com/spf13/pflag"
|
|
|
|
"github.com/zeebo/errs"
|
|
|
|
|
2023-06-30 11:13:18 +01:00
|
|
|
"storj.io/common/storj"
|
|
|
|
"storj.io/common/storj/location"
|
2023-07-07 09:31:58 +01:00
|
|
|
"storj.io/storj/satellite/nodeselection"
|
2023-06-30 11:13:18 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// PlacementRules can crate filter based on the placement identifier.
|
2023-08-01 12:50:22 +01:00
|
|
|
type PlacementRules func(constraint storj.PlacementConstraint) (filter nodeselection.NodeFilter)
|
2023-06-30 11:13:18 +01:00
|
|
|
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
// PlacementDefinitions can include the placement definitions for each known identifier.
|
|
|
|
type PlacementDefinitions struct {
|
2023-08-01 12:50:22 +01:00
|
|
|
placements map[storj.PlacementConstraint]nodeselection.NodeFilter
|
2023-06-30 11:13:18 +01:00
|
|
|
}
|
|
|
|
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
// ConfigurablePlacementRule is a string configuration includes all placement rules in the form of id1:def1,id2:def2...
|
|
|
|
type ConfigurablePlacementRule struct {
|
|
|
|
PlacementRules string
|
|
|
|
}
|
|
|
|
|
2023-07-06 13:35:26 +01:00
|
|
|
// String implements pflag.Value.
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
func (c *ConfigurablePlacementRule) String() string {
|
|
|
|
return c.PlacementRules
|
2023-07-06 13:35:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set implements pflag.Value.
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
func (c *ConfigurablePlacementRule) Set(s string) error {
|
|
|
|
c.PlacementRules = s
|
|
|
|
return nil
|
2023-07-06 13:35:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Type implements pflag.Value.
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
func (c *ConfigurablePlacementRule) Type() string {
|
|
|
|
return "configurable-placement-rule"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse creates the PlacementDefinitions from the string rules.
|
|
|
|
func (c ConfigurablePlacementRule) Parse() (*PlacementDefinitions, error) {
|
2023-09-25 13:49:32 +01:00
|
|
|
rules := c.PlacementRules
|
|
|
|
if _, err := os.Stat(rules); err == nil {
|
|
|
|
ruleBytes, err := os.ReadFile(rules)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errs.New("Placement definition file couldn't be read: %s %v", rules, err)
|
|
|
|
}
|
|
|
|
rules = string(ruleBytes)
|
|
|
|
}
|
|
|
|
if strings.HasPrefix(rules, "/") || strings.HasPrefix(rules, "./") || strings.HasPrefix(rules, "../") {
|
|
|
|
return nil, errs.New("Placement definition (%s) looks to be a path, but file doesn't exist at that place", rules)
|
|
|
|
}
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
d := NewPlacementDefinitions()
|
|
|
|
d.AddLegacyStaticRules()
|
2023-09-25 13:49:32 +01:00
|
|
|
err := d.AddPlacementFromString(rules)
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
return d, err
|
2023-07-06 13:35:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var _ pflag.Value = &ConfigurablePlacementRule{}
|
|
|
|
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
// NewPlacementDefinitions creates a fully initialized NewPlacementDefinitions.
|
|
|
|
func NewPlacementDefinitions() *PlacementDefinitions {
|
|
|
|
return &PlacementDefinitions{
|
2023-08-14 15:27:53 +01:00
|
|
|
placements: map[storj.PlacementConstraint]nodeselection.NodeFilter{
|
|
|
|
storj.EveryCountry: nodeselection.AnyFilter{}},
|
2023-06-30 11:13:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddLegacyStaticRules initializes all the placement rules defined earlier in static golang code.
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
func (d *PlacementDefinitions) AddLegacyStaticRules() {
|
2023-08-16 09:36:05 +01:00
|
|
|
d.placements[storj.EEA] = nodeselection.NodeFilters{nodeselection.NewCountryFilter(location.NewSet(nodeselection.EeaCountriesWithoutEu...).With(nodeselection.EuCountries...))}
|
|
|
|
d.placements[storj.EU] = nodeselection.NodeFilters{nodeselection.NewCountryFilter(location.NewSet(nodeselection.EuCountries...))}
|
2023-07-10 16:48:33 +01:00
|
|
|
d.placements[storj.US] = nodeselection.NodeFilters{nodeselection.NewCountryFilter(location.NewSet(location.UnitedStates))}
|
|
|
|
d.placements[storj.DE] = nodeselection.NodeFilters{nodeselection.NewCountryFilter(location.NewSet(location.Germany))}
|
2023-07-31 08:42:45 +01:00
|
|
|
d.placements[storj.NR] = nodeselection.NodeFilters{nodeselection.NewCountryFilter(location.NewFullSet().Without(location.Russia, location.Belarus, location.None))}
|
2023-06-30 11:13:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// AddPlacementRule registers a new placement.
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
func (d *PlacementDefinitions) AddPlacementRule(id storj.PlacementConstraint, filter nodeselection.NodeFilter) {
|
2023-08-01 12:50:22 +01:00
|
|
|
d.placements[id] = filter
|
2023-06-30 11:13:18 +01:00
|
|
|
}
|
|
|
|
|
2023-09-14 17:42:59 +01:00
|
|
|
type stringNotMatch string
|
|
|
|
|
2023-07-06 13:35:26 +01:00
|
|
|
// AddPlacementFromString parses placement definition form string representations from id:definition;id:definition;...
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
func (d *PlacementDefinitions) AddPlacementFromString(definitions string) error {
|
2023-07-06 13:35:26 +01:00
|
|
|
env := map[any]any{
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
"country": func(countries ...string) (nodeselection.NodeFilter, error) {
|
|
|
|
return nodeselection.NewCountryFilterFromString(countries)
|
2023-07-06 13:35:26 +01:00
|
|
|
},
|
2023-10-13 09:22:27 +01:00
|
|
|
"placement": func(ix int64) (nodeselection.NodeFilter, error) {
|
|
|
|
filter, found := d.placements[storj.PlacementConstraint(ix)]
|
|
|
|
if !found {
|
|
|
|
return nil, errs.New("Placement %d is referenced before defined. Please define it first!", ix)
|
|
|
|
}
|
|
|
|
return filter, nil
|
2023-08-16 09:36:05 +01:00
|
|
|
},
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
"all": func(filters ...nodeselection.NodeFilter) (nodeselection.NodeFilters, error) {
|
2023-07-06 13:35:26 +01:00
|
|
|
res := nodeselection.NodeFilters{}
|
|
|
|
for _, filter := range filters {
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
res = append(res, filter)
|
2023-07-06 13:35:26 +01:00
|
|
|
}
|
|
|
|
return res, nil
|
|
|
|
},
|
2023-08-16 09:36:05 +01:00
|
|
|
mito.OpAnd: 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("&& is supported only between NodeFilter instances")
|
|
|
|
}
|
|
|
|
res := nodeselection.NodeFilters{filter1, filter2}
|
|
|
|
return res, nil
|
|
|
|
},
|
2023-10-05 13:40:11 +01:00
|
|
|
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
|
|
|
|
},
|
2023-07-06 13:35:26 +01:00
|
|
|
"tag": func(nodeIDstr string, key string, value any) (nodeselection.NodeFilters, error) {
|
|
|
|
nodeID, err := storj.NodeIDFromString(nodeIDstr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-09-14 17:42:59 +01:00
|
|
|
|
2023-07-06 13:35:26 +01:00
|
|
|
var rawValue []byte
|
2023-09-14 17:42:59 +01:00
|
|
|
match := bytes.Equal
|
2023-07-06 13:35:26 +01:00
|
|
|
switch v := value.(type) {
|
|
|
|
case string:
|
|
|
|
rawValue = []byte(v)
|
|
|
|
case []byte:
|
|
|
|
rawValue = v
|
2023-09-14 17:42:59 +01:00
|
|
|
case stringNotMatch:
|
|
|
|
match = func(a, b []byte) bool {
|
|
|
|
return !bytes.Equal(a, b)
|
|
|
|
}
|
|
|
|
rawValue = []byte(v)
|
2023-07-06 13:35:26 +01:00
|
|
|
default:
|
|
|
|
return nil, errs.New("3rd argument of tag() should be string or []byte")
|
|
|
|
}
|
|
|
|
res := nodeselection.NodeFilters{
|
2023-09-14 17:42:59 +01:00
|
|
|
nodeselection.NewTagFilter(nodeID, key, rawValue, match),
|
2023-07-06 13:35:26 +01:00
|
|
|
}
|
|
|
|
return res, nil
|
|
|
|
},
|
2023-08-23 14:47:49 +01:00
|
|
|
"annotated": func(filter nodeselection.NodeFilter, kv ...nodeselection.Annotation) (nodeselection.AnnotatedNodeFilter, error) {
|
2023-08-01 12:50:22 +01:00
|
|
|
return nodeselection.AnnotatedNodeFilter{
|
|
|
|
Filter: filter,
|
|
|
|
Annotations: kv,
|
|
|
|
}, nil
|
|
|
|
},
|
2023-08-23 14:47:49 +01:00
|
|
|
"annotation": func(key string, value string) (nodeselection.Annotation, error) {
|
|
|
|
return nodeselection.Annotation{
|
|
|
|
Key: key,
|
|
|
|
Value: value,
|
2023-08-01 12:50:22 +01:00
|
|
|
}, nil
|
|
|
|
},
|
2023-08-14 12:30:27 +01:00
|
|
|
"exclude": func(filter nodeselection.NodeFilter) (nodeselection.NodeFilter, error) {
|
|
|
|
return nodeselection.NewExcludeFilter(filter), nil
|
|
|
|
},
|
2023-09-14 17:42:59 +01:00
|
|
|
"empty": func() string {
|
|
|
|
return ""
|
|
|
|
},
|
|
|
|
"notEmpty": func() any {
|
|
|
|
return stringNotMatch("")
|
|
|
|
},
|
2023-07-06 13:35:26 +01:00
|
|
|
}
|
|
|
|
for _, definition := range strings.Split(definitions, ";") {
|
|
|
|
definition = strings.TrimSpace(definition)
|
|
|
|
if definition == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
idDef := strings.SplitN(definition, ":", 2)
|
|
|
|
|
2023-09-25 13:49:32 +01:00
|
|
|
if len(idDef) != 2 {
|
|
|
|
return errs.New("placement definition should be in the form ID:definition (but it was %s)", definition)
|
|
|
|
}
|
2023-07-06 13:35:26 +01:00
|
|
|
val, err := mito.Eval(idDef[1], env)
|
|
|
|
if err != nil {
|
2023-10-13 09:22:27 +01:00
|
|
|
return errs.New("Error in line '%s' when placement rule is parsed: %v", idDef[1], err)
|
2023-07-06 13:35:26 +01:00
|
|
|
}
|
|
|
|
id, err := strconv.Atoi(idDef[0])
|
|
|
|
if err != nil {
|
|
|
|
return errs.Wrap(err)
|
|
|
|
}
|
2023-08-01 12:50:22 +01:00
|
|
|
d.placements[storj.PlacementConstraint(id)] = val.(nodeselection.NodeFilter)
|
2023-07-06 13:35:26 +01:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-06-30 11:13:18 +01:00
|
|
|
// CreateFilters implements PlacementCondition.
|
satellite/overlay: fix placement selection config parsing
When we do `satellite run api --placement '...'`, the placement rules are not parsed well.
The problem is based on `viper.AllSettings()`, and the main logic is sg. like this (from a new unit test):
```
r := ConfigurablePlacementRule{}
err := r.Set(p)
require.NoError(t, err)
serialized := r.String()
r2 := ConfigurablePlacementRule{}
err = r2.Set(serialized)
require.NoError(t, err)
require.Equal(t, p, r2.String())
```
All settings evaluates the placement rules in `ConfigurablePlacementRules` and stores the string representation.
The problem is that we don't have proper `String()` implementation (it prints out the structs instead of the original definition.
There are two main solutions for this problem:
1. We can fix the `String()`. When we parse a placement rule, the `String()` method should print out the original definition
2. We can switch to use pure string as configuration parameter, and parse the rules only when required.
I feel that 1 is error prone, we can do it (and in this patch I added a lot of `String()` implementations, but it's hard to be sure that our `String()` logic is inline with the parsing logic.
Therefore I decided to make the configuration value of the placements a string (or a wrapper around string).
That's the main reason why this patch seems to be big, as I updated all the usages.
But the main part is in beginning of the `placement.go` (configuration parsing is not a pflag.Value implementation any more, but a separated step).
And `filter.go`, (a few more String implementation for filters.
https://github.com/storj/storj/issues/6248
Change-Id: I47c762d3514342b76a2e85683b1c891502a0756a
2023-09-06 10:40:22 +01:00
|
|
|
func (d *PlacementDefinitions) CreateFilters(constraint storj.PlacementConstraint) (filter nodeselection.NodeFilter) {
|
2023-06-30 11:13:18 +01:00
|
|
|
if filters, found := d.placements[constraint]; found {
|
2023-08-01 12:50:22 +01:00
|
|
|
return filters
|
2023-07-10 16:01:48 +01:00
|
|
|
}
|
|
|
|
return nodeselection.NodeFilters{
|
|
|
|
nodeselection.ExcludeAllFilter{},
|
2023-06-30 11:13:18 +01:00
|
|
|
}
|
|
|
|
}
|
2023-09-25 13:49:32 +01:00
|
|
|
|
|
|
|
// SupportedPlacements returns all the IDs, which have associated placement rules.
|
|
|
|
func (d *PlacementDefinitions) SupportedPlacements() (res []storj.PlacementConstraint) {
|
|
|
|
for id := range d.placements {
|
|
|
|
res = append(res, id)
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|