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>
Antonio Navarro Perez committed
Oct 12, 2022 at 17:02 UTC
bf8274f6e2afb28a624b75859991cb164cb367ff
4 files changed
+135
-9
core/commands/swarm.go
+21
-8
@@ -63,10 +63,11 @@ ipfs peers in the internet.
63
}
64
65
const (
66
- swarmVerboseOptionName = "verbose"
67
- swarmStreamsOptionName = "streams"
68
- swarmLatencyOptionName = "latency"
69
- swarmDirectionOptionName = "direction"
66
+ swarmVerboseOptionName = "verbose"
67
+ swarmStreamsOptionName = "streams"
68
+ swarmLatencyOptionName = "latency"
69
+ swarmDirectionOptionName = "direction"
70
+ swarmResetLimitsOptionName = "reset"
71
)
72
73
type peeringResult struct {
@@ -387,6 +388,9 @@ Changes made via command line are persisted in the Swarm.ResourceMgr.Limits fiel
388
cmds.StringArg("scope", true, false, "scope of the limit"),
389
cmds.FileArg("limit.json", false, false, "limits to be set").EnableStdin(),
390
},
391
+ Options: []cmds.Option{
392
+ cmds.BoolOption(swarmResetLimitsOptionName, "reset limit to default"),
393
+ },
394
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
395
node, err := cmdenv.GetNode(env)
396
if err != nil {
@@ -418,10 +422,19 @@ Changes made via command line are persisted in the Swarm.ResourceMgr.Limits fiel
422
}
423
}
424
421
- // get scope limit
422
- result, err := libp2p.NetLimit(node.ResourceManager, scope)
423
- if err != nil {
424
- return err
425
+ var result rcmgr.BaseLimit
426
+ _, reset := req.Options[swarmResetLimitsOptionName]
427
+ if reset {
428
+ result, err = libp2p.NetResetLimit(node.ResourceManager, node.Repo, scope)
429
+ if err != nil {
430
+ return err
431
+ }
432
+ } else {
433
+ // get scope limit
434
+ result, err = libp2p.NetLimit(node.ResourceManager, scope)
435
+ if err != nil {
436
+ return err
437
+ }
438
}
439
440
b := new(bytes.Buffer)
core/node/libp2p/rcmgr.go
+98
@@ -347,3 +347,101 @@ func NetSetLimit(mgr network.ResourceManager, repo repo.Repo, scope string, limi
347
348
return nil
349
}
350
+
351
+// NetResetLimit resets ResourceManager limits to defaults. The limits take effect immediately, and are also persisted to the repo config.
352
+func NetResetLimit(mgr network.ResourceManager, repo repo.Repo, scope string) (rcmgr.BaseLimit, error) {
353
+ var result rcmgr.BaseLimit
354
+
355
+ setLimit := func(s network.ResourceScope, l rcmgr.Limit) error {
356
+ limiter, ok := s.(rcmgr.ResourceScopeLimiter)
357
+ if !ok {
358
+ return ErrNoResourceMgr
359
+ }
360
+
361
+ limiter.SetLimit(l)
362
+ return nil
363
+ }
364
+
365
+ cfg, err := repo.Config()
366
+ if err != nil {
367
+ return result, fmt.Errorf("reading config to reset limit: %w", err)
368
+ }
369
+
370
+ defaults := adjustedDefaultLimits(cfg.Swarm)
371
+
372
+ if cfg.Swarm.ResourceMgr.Limits == nil {
373
+ cfg.Swarm.ResourceMgr.Limits = &rcmgr.LimitConfig{}
374
+ }
375
+ configLimits := cfg.Swarm.ResourceMgr.Limits
376
+
377
+ var setConfigFunc func() rcmgr.BaseLimit
378
+ switch {
379
+ case scope == config.ResourceMgrSystemScope:
380
+ err = mgr.ViewSystem(func(s network.ResourceScope) error { return setLimit(s, &defaults.System) })
381
+ setConfigFunc = func() rcmgr.BaseLimit {
382
+ configLimits.System = defaults.System
383
+ return defaults.System
384
+ }
385
+ case scope == config.ResourceMgrTransientScope:
386
+ err = mgr.ViewTransient(func(s network.ResourceScope) error { return setLimit(s, &defaults.Transient) })
387
+ setConfigFunc = func() rcmgr.BaseLimit {
388
+ configLimits.Transient = defaults.Transient
389
+ return defaults.Transient
390
+ }
391
+ case strings.HasPrefix(scope, config.ResourceMgrServiceScopePrefix):
392
+ svc := strings.TrimPrefix(scope, config.ResourceMgrServiceScopePrefix)
393
+
394
+ err = mgr.ViewService(svc, func(s network.ServiceScope) error { return setLimit(s, &defaults.ServiceDefault) })
395
+ setConfigFunc = func() rcmgr.BaseLimit {
396
+ if configLimits.Service == nil {
397
+ configLimits.Service = map[string]rcmgr.BaseLimit{}
398
+ }
399
+ configLimits.Service[svc] = defaults.ServiceDefault
400
+ return defaults.ServiceDefault
401
+ }
402
+ case strings.HasPrefix(scope, config.ResourceMgrProtocolScopePrefix):
403
+ proto := strings.TrimPrefix(scope, config.ResourceMgrProtocolScopePrefix)
404
+
405
+ err = mgr.ViewProtocol(protocol.ID(proto), func(s network.ProtocolScope) error { return setLimit(s, &defaults.ProtocolDefault) })
406
+ setConfigFunc = func() rcmgr.BaseLimit {
407
+ if configLimits.Protocol == nil {
408
+ configLimits.Protocol = map[protocol.ID]rcmgr.BaseLimit{}
409
+ }
410
+ configLimits.Protocol[protocol.ID(proto)] = defaults.ProtocolDefault
411
+
412
+ return defaults.ProtocolDefault
413
+ }
414
+ case strings.HasPrefix(scope, config.ResourceMgrPeerScopePrefix):
415
+ p := strings.TrimPrefix(scope, config.ResourceMgrPeerScopePrefix)
416
+
417
+ var pid peer.ID
418
+ pid, err = peer.Decode(p)
419
+ if err != nil {
420
+ return result, fmt.Errorf("invalid peer ID: %q: %w", p, err)
421
+ }
422
+
423
+ err = mgr.ViewPeer(pid, func(s network.PeerScope) error { return setLimit(s, &defaults.PeerDefault) })
424
+ setConfigFunc = func() rcmgr.BaseLimit {
425
+ if configLimits.Peer == nil {
426
+ configLimits.Peer = map[peer.ID]rcmgr.BaseLimit{}
427
+ }
428
+ configLimits.Peer[pid] = defaults.PeerDefault
429
+
430
+ return defaults.PeerDefault
431
+ }
432
+ default:
433
+ return result, fmt.Errorf("invalid scope %q", scope)
434
+ }
435
+
436
+ if err != nil {
437
+ return result, fmt.Errorf("resetting new limits on resource manager: %w", err)
438
+ }
439
+
440
+ result = setConfigFunc()
441
+
442
+ if err := repo.SetConfig(cfg); err != nil {
443
+ return result, fmt.Errorf("writing new limits to repo config: %w", err)
444
+ }
445
+
446
+ return result, nil
447
+}
core/node/libp2p/rcmgr_defaults.go
-1
@@ -21,7 +21,6 @@ import (
21
func adjustedDefaultLimits(cfg config.SwarmConfig) rcmgr.LimitConfig {
22
// Run checks to avoid introducing regressions
23
if os.Getenv("IPFS_CHECK_RCMGR_DEFAULTS") != "" {
24
- // FIXME: Broken. Being tracked in https://github.com/ipfs/go-ipfs/issues/8949.
24
checkImplicitDefaults()
25
}
26
defaultLimits := rcmgr.DefaultLimits
test/sharness/t0139-swarm-rcmgr.sh
+16
@@ -54,6 +54,22 @@ test_expect_success 'ResourceMgr enabled: swarm limit' '
54
jq -e .StreamsInbound < json &&
55
jq -e .StreamsOutbound < json
56
'
57
+test_expect_success 'ResourceMgr enabled: swarm limit reset' '
58
+ ipfs swarm limit system --reset --enc=json 2> reset &&
59
+ ipfs swarm limit system --enc=json 2> actual &&
60
+ test_cmp reset actual
61
+'
62
+
63
+test_expect_success 'ResourceMgr enabled: swarm limit reset on map values' '
64
+ ipfs swarm limit peer:12D3KooWL7i1T9VSPeF8AgQApbyM51GNKZsYPvNvL347aMDmvNzG --reset --enc=json 2> reset &&
65
+ ipfs swarm limit peer:12D3KooWL7i1T9VSPeF8AgQApbyM51GNKZsYPvNvL347aMDmvNzG --enc=json 2> actual &&
66
+ test_cmp reset actual
67
+'
68
+
69
+test_expect_success 'ResourceMgr enabled: scope is required using reset flag' '
70
+ test_expect_code 1 ipfs swarm limit --reset 2> actual &&
71
+ test_should_contain "Error: argument \"scope\" is required" actual
72
+'
73
74
test_expect_success 'connected: swarm stats all working properly' '
75
test_expect_code 0 ipfs swarm stats all