Skip to content

Commit

Permalink
*: Add regions config option
Browse files Browse the repository at this point in the history
Closes #989.

Signed-off-by: Evgenii Baidakov <[email protected]>
  • Loading branch information
smallhive committed Sep 16, 2024
1 parent 19810b2 commit c8f8b3a
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ This document outlines major changes between releases.
## [Unreleased]

### Added
- Config option placement_policy.regions as alternative for placement_policy.region_mapping (#989)

### Changed

Expand Down
76 changes: 59 additions & 17 deletions cmd/s3-gw/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,31 @@ func (a *App) initLayer(ctx context.Context, anonSigner user.Signer, neoFS *neof
}
}

func loadRegions(v *viper.Viper) (map[string]string, error) {
var (
rawRegions = v.GetStringMap(cfgPolicyRegions)
regions = make(map[string]string, len(rawRegions))
)

for key, val := range rawRegions {
if s, ok := val.(string); ok {
regions[key] = s
continue
}

return nil, fmt.Errorf("region %q values is not a string: %s", key, val)
}

return regions, nil
}

func newAppSettings(log *Logger, v *viper.Viper) *appSettings {
policies, err := newPlacementPolicy(getDefaultPolicyValue(v), v.GetString(cfgPolicyRegionMapFile))
regions, err := loadRegions(v)
if err != nil {
log.logger.Fatal("load regions failed", zap.Error(err))
}

policies, err := newPlacementPolicy(getDefaultPolicyValue(v), v.GetString(cfgPolicyRegionMapFile), regions)
if err != nil {
log.logger.Fatal("failed to create new policy mapping", zap.Error(err))
}
Expand Down Expand Up @@ -311,12 +334,12 @@ func getPool(ctx context.Context, logger *zap.Logger, cfg *viper.Viper) (*pool.P
return p, key, poolStat
}

func newPlacementPolicy(defaultPolicy string, regionPolicyFilepath string) (*placementPolicy, error) {
func newPlacementPolicy(defaultPolicy string, regionPolicyFilepath string, regions map[string]string) (*placementPolicy, error) {
policies := &placementPolicy{
regionMap: make(map[string]netmap.PlacementPolicy),
}

return policies, policies.update(defaultPolicy, regionPolicyFilepath)
return policies, policies.update(defaultPolicy, regionPolicyFilepath, regions)
}

func (p *placementPolicy) Default() netmap.PlacementPolicy {
Expand All @@ -333,19 +356,10 @@ func (p *placementPolicy) Get(name string) (netmap.PlacementPolicy, bool) {
return policy, ok
}

func (p *placementPolicy) update(defaultPolicy string, regionPolicyFilepath string) error {
var defaultPlacementPolicy netmap.PlacementPolicy
if err := defaultPlacementPolicy.DecodeString(defaultPolicy); err != nil {
return fmt.Errorf("parse default policy '%s': %w", defaultPolicy, err)
}

regionPolicyMap, err := readRegionMap(regionPolicyFilepath)
if err != nil {
return fmt.Errorf("read region map file: %w", err)
}
func parsePolicies(regionMap map[string]netmap.PlacementPolicy, regions map[string]string) error {
var err error

regionMap := make(map[string]netmap.PlacementPolicy, len(regionPolicyMap))
for region, policy := range regionPolicyMap {
for region, policy := range regions {
var pp netmap.PlacementPolicy
if err = pp.DecodeString(policy); err == nil {
regionMap[region] = pp
Expand All @@ -357,7 +371,30 @@ func (p *placementPolicy) update(defaultPolicy string, regionPolicyFilepath stri
continue
}

return fmt.Errorf("parse region '%s' to policy mapping: %w", region, err)
return fmt.Errorf("%q: %w", region, err)
}

return nil
}

func (p *placementPolicy) update(defaultPolicy string, regionPolicyFilepath string, regions map[string]string) error {
var defaultPlacementPolicy netmap.PlacementPolicy
if err := defaultPlacementPolicy.DecodeString(defaultPolicy); err != nil {
return fmt.Errorf("parse default policy '%s': %w", defaultPolicy, err)
}

regionPolicyMap, err := readRegionMap(regionPolicyFilepath)
if err != nil {
return fmt.Errorf("read region map file: %w", err)
}

regionMap := make(map[string]netmap.PlacementPolicy, len(regionPolicyMap)+len(regions))
if err = parsePolicies(regionMap, regionPolicyMap); err != nil {
return fmt.Errorf("parse region map: %w", err)
}

if err = parsePolicies(regionMap, regions); err != nil {
return fmt.Errorf("parse regions: %w", err)
}

p.mu.Lock()
Expand Down Expand Up @@ -522,7 +559,12 @@ func (a *App) updateSettings() {
a.settings.logLevel.SetLevel(lvl)
}

if err := a.settings.policies.update(getDefaultPolicyValue(a.cfg), a.cfg.GetString(cfgPolicyRegionMapFile)); err != nil {
regions, err := loadRegions(a.cfg)
if err != nil {
a.log.Warn("regions won't be updated", zap.Error(err))
}

if err := a.settings.policies.update(getDefaultPolicyValue(a.cfg), a.cfg.GetString(cfgPolicyRegionMapFile), regions); err != nil {
a.log.Warn("policies won't be updated", zap.Error(err))
}
}
Expand Down
1 change: 1 addition & 0 deletions cmd/s3-gw/app_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ const ( // Settings.
// Policy.
cfgPolicyDefault = "placement_policy.default"
cfgPolicyRegionMapFile = "placement_policy.region_mapping"
cfgPolicyRegions = "placement_policy.regions"

// CORS.
cfgDefaultMaxAge = "cors.default_max_age"
Expand Down
4 changes: 4 additions & 0 deletions config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ placement_policy:
# Region to placement policy mapping json file.
# Path to container policy mapping. The same as '--container-policy' flag for authmate
region_mapping: /path/to/container/policy.json
regions:
REP-1: "REP 1"
REP-3: "REP 3"
complex: "REP 1 IN X CBF 1 SELECT 1 FROM * AS X"

# CORS
# value of Access-Control-Max-Age header if this value is not set in a rule. Has an int type.
Expand Down
10 changes: 10 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ placement_policy:
|------------------|----------|---------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `default` | `string` | yes | `REP 3` | Default policy of placing containers in NeoFS. If a user sends a request `CreateBucket` and doesn't define policy for placing of a container in NeoFS, the S3 Gateway will put the container with default policy. |
| `region_mapping` | `string` | yes | | Path to file that maps aws `LocationContraint` values to NeoFS placement policy. The similar to `--container-policy` flag in `neofs-s3-authmate` util, see in [docs](./authmate.md#containers-policy) |
| `regions` | `map` | yes | | The hashtable than maps aws `LocationContraint` values to NeoFS placement policy. The similar to `region_mapping` config option. The values extends/overrides values from region_mapping file, if it provided. |

File for `region_mapping` must contain something like this:

Expand All @@ -272,6 +273,15 @@ File for `region_mapping` must contain something like this:
}
```

The option `placement_policy.regions` may look like:
```yaml
placement_policy:
regions:
REP-1: "REP 1"
REP-3: "REP 3"
complex: "REP 1 IN X CBF 1 SELECT 1 FROM * AS X"
```

**Note:** on SIGHUP reload policies will be updated only if both parameters are valid.
So if you change `default` to some valid value and set invalid path in `region_mapping` the `default` value won't be changed.

Expand Down

0 comments on commit c8f8b3a

Please sign in to comment.