diff --git a/core/commands/swarm.go b/core/commands/swarm.go index bf40acd5eca..ef5f9c8be98 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -67,6 +67,7 @@ const ( swarmStreamsOptionName = "streams" swarmLatencyOptionName = "latency" swarmDirectionOptionName = "direction" + swarmSaveOptionName = "save" ) type peeringResult struct { @@ -101,6 +102,9 @@ var swarmPeeringAddCmd = &cmds.Command{ Arguments: []cmds.Argument{ cmds.StringArg("address", true, true, "address of peer to add into the peering subsystem"), }, + Options: []cmds.Option{ + cmds.BoolOption(swarmSaveOptionName, "if set, address(es) will be saved to peering config"), + }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { addrs := make([]ma.Multiaddr, len(req.Arguments)) @@ -130,6 +134,30 @@ var swarmPeeringAddCmd = &cmds.Command{ return err } } + + save, _ := req.Options[swarmSaveOptionName].(bool) + if save { + r, err := fsrepo.Open(env.(*commands.Context).ConfigRoot) + if err != nil { + return err + } + defer r.Close() + cfg, err := r.Config() + if err != nil { + return err + } + + addrInfos, err := mergeAddrInfo(addInfos, cfg.Peering.Peers) + if err != nil { + return fmt.Errorf("error merging peers: %w", err) + } + + cfg.Peering.Peers = addrInfos + if err := r.SetConfig(cfg); err != nil { + return fmt.Errorf("error writing new peers to repo config: %w", err) + } + } + return nil }, Encoders: cmds.EncoderMap{ @@ -184,6 +212,9 @@ var swarmPeeringRmCmd = &cmds.Command{ Arguments: []cmds.Argument{ cmds.StringArg("ID", true, true, "ID of peer to remove from the peering subsystem"), }, + Options: []cmds.Option{ + cmds.BoolOption(swarmSaveOptionName, "if set, address(es) will be removed from peering config"), + }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { node, err := cmdenv.GetNode(env) if err != nil { @@ -201,12 +232,31 @@ var swarmPeeringRmCmd = &cmds.Command{ return err } } + + save, _ := req.Options[swarmSaveOptionName].(bool) + if save { + r, err := fsrepo.Open(env.(*commands.Context).ConfigRoot) + if err != nil { + return err + } + defer r.Close() + cfg, err := r.Config() + if err != nil { + return err + } + + cfg.Peering.Peers = node.Peering.ListPeers() + if err := r.SetConfig(cfg); err != nil { + return fmt.Errorf("error removing peers from repo config: %w", err) + } + } + return nil }, Type: peeringResult{}, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, pr *peeringResult) error { - fmt.Fprintf(w, "add %s %s\n", pr.ID.String(), pr.Status) + fmt.Fprintf(w, "rm %s %s\n", pr.ID.String(), pr.Status) return nil }), }, @@ -1057,3 +1107,17 @@ func filtersRemove(r repo.Repo, cfg *config.Config, toRemoveFilters []string) ([ return removed, nil } + +func mergeAddrInfo(addrInfos ...[]peer.AddrInfo) ([]peer.AddrInfo, error) { + var addrs []ma.Multiaddr + for _, infos := range addrInfos { + for _, addrInfo := range infos { + addr, err := peer.AddrInfoToP2pAddrs(&addrInfo) + if err != nil { + return nil, err + } + addrs = append(addrs, addr...) + } + } + return peer.AddrInfosFromP2pAddrs(addrs...) +} diff --git a/test/sharness/t0140-swarm.sh b/test/sharness/t0140-swarm.sh index d65831d3e22..2851bb9ac08 100755 --- a/test/sharness/t0140-swarm.sh +++ b/test/sharness/t0140-swarm.sh @@ -160,6 +160,35 @@ test_expect_success 'peering is removed' ' test_kill_ipfs_daemon +test_launch_ipfs_daemon + +peeringID='QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N' +peeringID2='QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5K' +peeringAddr='/ip4/1.2.3.4/tcp/1234/p2p/QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N' +peeringAddr2='/ip4/1.2.3.4/tcp/1234/p2p/QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5K' + +test_expect_success "'ipfs swarm peering add' with save option mutates config" ' + ipfs config Peering.Peers > start-peers && + ipfs swarm peering add ${peeringAddr} ${peeringAddr2} --save && + ipfs config Peering.Peers > end-peers && + ! test_cmp start-peers end-peers && + test_should_contain "${peeringID}" end-peers && + test_should_contain ${peeringID2} end-peers && + rm start-peers end-peers +' + +test_expect_success "'ipfs swarm peering rm' with save option mutates config" ' + ipfs config Peering.Peers > start-peers && + ipfs swarm peering rm ${peeringID} --save && + ipfs config Peering.Peers > end-peers && + ! test_cmp start-peers end-peers && + test_should_not_contain "${peeringID}" end-peers && + test_should_contain ${peeringID2} end-peers && + rm start-peers end-peers +' + +test_kill_ipfs_daemon + test_expect_success "set up tcp testbed" ' iptb testbed create -type localipfs -count 2 -force -init '