feat: --reset flag on swarm limit command (#9310)

* feat: --reset flag on swarm limit command

This flag allows to the user to reset limits to default values.

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>

* Use adjusted default limits and remove already fixed FIXME

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>

* Apply suggestions from code review

Co-authored-by: Gus Eggert <gus@gus.dev>

* Return correct defaults

* Remove resetting all values from a map.

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>

Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
Co-authored-by: Gus Eggert <gus@gus.dev>
This commit is contained in:
Antonio Navarro Perez 2022-10-12 17:02:43 +02:00 committed by GitHub
parent 4291d6b236
commit bf8274f6e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 135 additions and 9 deletions

View File

@ -63,10 +63,11 @@ ipfs peers in the internet.
}
const (
swarmVerboseOptionName = "verbose"
swarmStreamsOptionName = "streams"
swarmLatencyOptionName = "latency"
swarmDirectionOptionName = "direction"
swarmVerboseOptionName = "verbose"
swarmStreamsOptionName = "streams"
swarmLatencyOptionName = "latency"
swarmDirectionOptionName = "direction"
swarmResetLimitsOptionName = "reset"
)
type peeringResult struct {
@ -387,6 +388,9 @@ Changes made via command line are persisted in the Swarm.ResourceMgr.Limits fiel
cmds.StringArg("scope", true, false, "scope of the limit"),
cmds.FileArg("limit.json", false, false, "limits to be set").EnableStdin(),
},
Options: []cmds.Option{
cmds.BoolOption(swarmResetLimitsOptionName, "reset limit to default"),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
node, err := cmdenv.GetNode(env)
if err != nil {
@ -418,10 +422,19 @@ Changes made via command line are persisted in the Swarm.ResourceMgr.Limits fiel
}
}
// get scope limit
result, err := libp2p.NetLimit(node.ResourceManager, scope)
if err != nil {
return err
var result rcmgr.BaseLimit
_, reset := req.Options[swarmResetLimitsOptionName]
if reset {
result, err = libp2p.NetResetLimit(node.ResourceManager, node.Repo, scope)
if err != nil {
return err
}
} else {
// get scope limit
result, err = libp2p.NetLimit(node.ResourceManager, scope)
if err != nil {
return err
}
}
b := new(bytes.Buffer)

View File

@ -347,3 +347,101 @@ func NetSetLimit(mgr network.ResourceManager, repo repo.Repo, scope string, limi
return nil
}
// NetResetLimit resets ResourceManager limits to defaults. The limits take effect immediately, and are also persisted to the repo config.
func NetResetLimit(mgr network.ResourceManager, repo repo.Repo, scope string) (rcmgr.BaseLimit, error) {
var result rcmgr.BaseLimit
setLimit := func(s network.ResourceScope, l rcmgr.Limit) error {
limiter, ok := s.(rcmgr.ResourceScopeLimiter)
if !ok {
return ErrNoResourceMgr
}
limiter.SetLimit(l)
return nil
}
cfg, err := repo.Config()
if err != nil {
return result, fmt.Errorf("reading config to reset limit: %w", err)
}
defaults := adjustedDefaultLimits(cfg.Swarm)
if cfg.Swarm.ResourceMgr.Limits == nil {
cfg.Swarm.ResourceMgr.Limits = &rcmgr.LimitConfig{}
}
configLimits := cfg.Swarm.ResourceMgr.Limits
var setConfigFunc func() rcmgr.BaseLimit
switch {
case scope == config.ResourceMgrSystemScope:
err = mgr.ViewSystem(func(s network.ResourceScope) error { return setLimit(s, &defaults.System) })
setConfigFunc = func() rcmgr.BaseLimit {
configLimits.System = defaults.System
return defaults.System
}
case scope == config.ResourceMgrTransientScope:
err = mgr.ViewTransient(func(s network.ResourceScope) error { return setLimit(s, &defaults.Transient) })
setConfigFunc = func() rcmgr.BaseLimit {
configLimits.Transient = defaults.Transient
return defaults.Transient
}
case strings.HasPrefix(scope, config.ResourceMgrServiceScopePrefix):
svc := strings.TrimPrefix(scope, config.ResourceMgrServiceScopePrefix)
err = mgr.ViewService(svc, func(s network.ServiceScope) error { return setLimit(s, &defaults.ServiceDefault) })
setConfigFunc = func() rcmgr.BaseLimit {
if configLimits.Service == nil {
configLimits.Service = map[string]rcmgr.BaseLimit{}
}
configLimits.Service[svc] = defaults.ServiceDefault
return defaults.ServiceDefault
}
case strings.HasPrefix(scope, config.ResourceMgrProtocolScopePrefix):
proto := strings.TrimPrefix(scope, config.ResourceMgrProtocolScopePrefix)
err = mgr.ViewProtocol(protocol.ID(proto), func(s network.ProtocolScope) error { return setLimit(s, &defaults.ProtocolDefault) })
setConfigFunc = func() rcmgr.BaseLimit {
if configLimits.Protocol == nil {
configLimits.Protocol = map[protocol.ID]rcmgr.BaseLimit{}
}
configLimits.Protocol[protocol.ID(proto)] = defaults.ProtocolDefault
return defaults.ProtocolDefault
}
case strings.HasPrefix(scope, config.ResourceMgrPeerScopePrefix):
p := strings.TrimPrefix(scope, config.ResourceMgrPeerScopePrefix)
var pid peer.ID
pid, err = peer.Decode(p)
if err != nil {
return result, fmt.Errorf("invalid peer ID: %q: %w", p, err)
}
err = mgr.ViewPeer(pid, func(s network.PeerScope) error { return setLimit(s, &defaults.PeerDefault) })
setConfigFunc = func() rcmgr.BaseLimit {
if configLimits.Peer == nil {
configLimits.Peer = map[peer.ID]rcmgr.BaseLimit{}
}
configLimits.Peer[pid] = defaults.PeerDefault
return defaults.PeerDefault
}
default:
return result, fmt.Errorf("invalid scope %q", scope)
}
if err != nil {
return result, fmt.Errorf("resetting new limits on resource manager: %w", err)
}
result = setConfigFunc()
if err := repo.SetConfig(cfg); err != nil {
return result, fmt.Errorf("writing new limits to repo config: %w", err)
}
return result, nil
}

View File

@ -21,7 +21,6 @@ import (
func adjustedDefaultLimits(cfg config.SwarmConfig) rcmgr.LimitConfig {
// Run checks to avoid introducing regressions
if os.Getenv("IPFS_CHECK_RCMGR_DEFAULTS") != "" {
// FIXME: Broken. Being tracked in https://github.com/ipfs/go-ipfs/issues/8949.
checkImplicitDefaults()
}
defaultLimits := rcmgr.DefaultLimits

View File

@ -54,6 +54,22 @@ test_expect_success 'ResourceMgr enabled: swarm limit' '
jq -e .StreamsInbound < json &&
jq -e .StreamsOutbound < json
'
test_expect_success 'ResourceMgr enabled: swarm limit reset' '
ipfs swarm limit system --reset --enc=json 2> reset &&
ipfs swarm limit system --enc=json 2> actual &&
test_cmp reset actual
'
test_expect_success 'ResourceMgr enabled: swarm limit reset on map values' '
ipfs swarm limit peer:12D3KooWL7i1T9VSPeF8AgQApbyM51GNKZsYPvNvL347aMDmvNzG --reset --enc=json 2> reset &&
ipfs swarm limit peer:12D3KooWL7i1T9VSPeF8AgQApbyM51GNKZsYPvNvL347aMDmvNzG --enc=json 2> actual &&
test_cmp reset actual
'
test_expect_success 'ResourceMgr enabled: scope is required using reset flag' '
test_expect_code 1 ipfs swarm limit --reset 2> actual &&
test_should_contain "Error: argument \"scope\" is required" actual
'
test_expect_success 'connected: swarm stats all working properly' '
test_expect_code 0 ipfs swarm stats all