Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 9666ff1

Browse files
authored
Merge pull request #669 from ipfs/feat/bootstrap-rm
Implement more bootstrap commands
2 parents 6faab2e + 7a5c571 commit 9666ff1

File tree

11 files changed

+265
-121
lines changed

11 files changed

+265
-121
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"ncp": "^2.0.0",
6767
"nexpect": "^0.5.0",
6868
"pre-commit": "^1.2.1",
69+
"qs": "^6.3.0",
6970
"rimraf": "^2.5.4",
7071
"stream-to-promise": "^2.2.0",
7172
"transform-loader": "^0.2.3"

src/cli/commands/bootstrap/add.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,30 @@ const utils = require('../../utils')
66
log.error = debug('cli:bootstrap:error')
77

88
module.exports = {
9-
command: 'add <peer>',
9+
command: 'add [<peer>]',
1010

1111
describe: 'Add peers to the bootstrap list',
1212

13-
builder: {},
13+
builder: {
14+
default: {
15+
describe: 'Add default bootstrap nodes.',
16+
type: 'boolean',
17+
default: false
18+
}
19+
},
1420

1521
handler (argv) {
1622
utils.getIPFS((err, ipfs) => {
1723
if (err) {
1824
throw err
1925
}
2026

21-
ipfs.bootstrap.add(argv.peer, (err, list) => {
27+
ipfs.bootstrap.add(argv.peer, {default: argv.default}, (err, list) => {
2228
if (err) {
2329
throw err
2430
}
31+
32+
list.Peers.forEach((l) => console.log(l))
2533
})
2634
})
2735
}

src/cli/commands/bootstrap/list.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ module.exports = {
2121
if (err) {
2222
throw err
2323
}
24-
list.forEach((node) => {
24+
25+
list.Peers.forEach((node) => {
2526
console.log(node)
2627
})
2728
})

src/cli/commands/bootstrap/rm.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,30 @@ log.error = debug('cli:bootstrap:error')
66
const utils = require('../../utils')
77

88
module.exports = {
9-
command: 'rm <peer>',
9+
command: 'rm [<peer>]',
1010

1111
describe: 'Removes peers from the bootstrap list',
1212

13-
builder: {},
13+
builder: {
14+
all: {
15+
type: 'boolean',
16+
describe: 'Remove all bootstrap peers.',
17+
default: false
18+
}
19+
},
1420

1521
handler (argv) {
1622
utils.getIPFS((err, ipfs) => {
1723
if (err) {
1824
throw err
1925
}
20-
ipfs.bootstrap.rm(argv.peer, (err, list) => {
26+
27+
ipfs.bootstrap.rm(argv.peer, {all: argv.all}, (err, list) => {
2128
if (err) {
2229
throw err
2330
}
31+
32+
list.Peers.forEach((l) => console.log(l))
2433
})
2534
})
2635
}

src/core/components/bootstrap.js

+42-11
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,69 @@
11
'use strict'
22

3+
const defaultNodes = require('../../init-files/default-config.json').Bootstrap
4+
35
module.exports = function bootstrap (self) {
46
return {
57
list: (callback) => {
68
self._repo.config.get((err, config) => {
79
if (err) {
810
return callback(err)
911
}
10-
callback(null, config.Bootstrap)
12+
callback(null, {Peers: config.Bootstrap})
1113
})
1214
},
13-
add: (multiaddr, callback) => {
15+
add: (multiaddr, args, callback) => {
16+
if (typeof args === 'function') {
17+
callback = args
18+
args = {default: false}
19+
}
1420
self._repo.config.get((err, config) => {
1521
if (err) {
1622
return callback(err)
1723
}
18-
config.Bootstrap.push(multiaddr)
19-
self._repo.config.set(config, callback)
24+
if (args.default) {
25+
config.Bootstrap = defaultNodes
26+
} else if (multiaddr) {
27+
config.Bootstrap.push(multiaddr)
28+
}
29+
self._repo.config.set(config, (err) => {
30+
if (err) {
31+
return callback(err)
32+
}
33+
34+
callback(null, {
35+
Peers: args.default ? defaultNodes : [multiaddr]
36+
})
37+
})
2038
})
2139
},
22-
rm: (multiaddr, callback) => {
40+
rm: (multiaddr, args, callback) => {
41+
if (typeof args === 'function') {
42+
callback = args
43+
args = {all: false}
44+
}
2345
self._repo.config.get((err, config) => {
2446
if (err) {
2547
return callback(err)
2648
}
49+
if (args.all) {
50+
config.Bootstrap = []
51+
} else {
52+
config.Bootstrap = config.Bootstrap.filter((mh) => mh !== multiaddr)
53+
}
54+
55+
self._repo.config.set(config, (err) => {
56+
if (err) {
57+
return callback(err)
58+
}
2759

28-
config.Bootstrap = config.Bootstrap.filter((mh) => {
29-
if (mh === multiaddr) {
30-
return false
31-
} else {
32-
return true
60+
const res = []
61+
if (!args.all && multiaddr) {
62+
res.push(multiaddr)
3363
}
64+
65+
callback(null, {Peers: res})
3466
})
35-
self._repo.config.set(config, callback)
3667
})
3768
}
3869
}

src/http-api/resources/bootstrap.js

+52-27
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,90 @@
11
'use strict'
22

3-
const boom = require('boom')
43
const multiaddr = require('multiaddr')
54

65
exports = module.exports
76

8-
// common pre request handler that parses the args and returns `key` which is assigned to `request.pre.args`
9-
exports.parseKey = (request, reply) => {
10-
if (!request.query.arg) {
11-
return reply("Argument 'multiaddr' is required").code(400).takeover()
12-
}
13-
14-
try {
15-
return reply({
16-
addr: multiaddr(request.query.arg)
17-
})
18-
} catch (err) {
19-
return reply({
20-
Message: 'Not a valid multiaddr',
21-
Code: 0
22-
}).code(500).takeover()
23-
}
7+
function applyError (reply, err) {
8+
reply({
9+
Message: err.message,
10+
Code: 0
11+
}).code(500).takeover()
2412
}
2513

2614
exports.list = (request, reply) => {
2715
const ipfs = request.server.app.ipfs
16+
2817
ipfs.bootstrap.list((err, list) => {
2918
if (err) {
30-
return reply(boom.badRequest(err))
19+
return applyError(reply, err)
3120
}
21+
3222
return reply(list)
3323
})
3424
}
3525

3626
exports.add = {
37-
parseArgs: exports.parseKey,
27+
parseArgs (request, reply) {
28+
const q = request.query
29+
const def = q.default === 'true'
30+
31+
if (q.arg != null) {
32+
try {
33+
return reply({
34+
addr: multiaddr(q.arg),
35+
default: def
36+
})
37+
} catch (err) {
38+
return applyError(reply, new Error('Not a valid multiaddr'))
39+
}
40+
} else {
41+
reply({default: def})
42+
}
43+
},
3844
handler (request, reply) {
3945
const ipfs = request.server.app.ipfs
4046
const addr = request.pre.args.addr
41-
console.log('Handler is called', addr.toString())
47+
const def = request.pre.args.default
4248

43-
ipfs.bootstrap.add(addr.toString(), (err, list) => {
49+
ipfs.bootstrap.add(addr && addr.toString(), {default: def}, (err, list) => {
4450
if (err) {
45-
return reply(boom.badRequest(err))
51+
return applyError(reply, err)
4652
}
47-
return reply()
53+
54+
return reply(list)
4855
})
4956
}
5057
}
5158

5259
exports.rm = {
53-
parseArgs: exports.parseKey,
60+
parseArgs (request, reply) {
61+
const q = request.query
62+
const all = q.all === 'true'
63+
64+
if (q.arg != null) {
65+
try {
66+
return reply({
67+
addr: multiaddr(q.arg),
68+
all: all
69+
})
70+
} catch (err) {
71+
return applyError(reply, new Error('Not a valid multiaddr'))
72+
}
73+
} else {
74+
reply({all: all})
75+
}
76+
},
5477
handler (request, reply) {
5578
const ipfs = request.server.app.ipfs
5679
const addr = request.pre.args.addr
80+
const all = request.pre.args.all
5781

58-
ipfs.bootstrap.rm(addr.toString(), (err, list) => {
82+
ipfs.bootstrap.rm(addr && addr.toString(), {all: all}, (err, list) => {
5983
if (err) {
60-
return reply(boom.badRequest(err))
84+
return applyError(reply, err)
6185
}
62-
return reply()
86+
87+
return reply(list)
6388
})
6489
}
6590
}

src/http-api/routes/bootstrap.js

+5-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict'
22

3-
const Joi = require('joi')
43
const resources = require('./../resources')
54

65
module.exports = (server) => {
@@ -10,7 +9,9 @@ module.exports = (server) => {
109
api.route({
1110
method: '*',
1211
path: '/api/v0/bootstrap',
13-
handler: resources.bootstrap.list
12+
config: {
13+
handler: resources.bootstrap.list
14+
}
1415
})
1516

1617
// https://github.com/ipfs/http-api-spec/blob/master/apiary.apib#L866
@@ -21,14 +22,7 @@ module.exports = (server) => {
2122
pre: [
2223
{ method: resources.bootstrap.add.parseArgs, assign: 'args' }
2324
],
24-
handler: resources.bootstrap.add.handler,
25-
validate: {
26-
query: {
27-
arg: Joi.string().required(),
28-
default: Joi.boolean(),
29-
'stream-channels': Joi.boolean()
30-
}
31-
}
25+
handler: resources.bootstrap.add.handler
3226
}
3327
})
3428

@@ -47,14 +41,7 @@ module.exports = (server) => {
4741
pre: [
4842
{ method: resources.bootstrap.rm.parseArgs, assign: 'args' }
4943
],
50-
handler: resources.bootstrap.rm.handler,
51-
validate: {
52-
query: {
53-
arg: Joi.string().required(),
54-
default: Joi.boolean(),
55-
'stream-channels': Joi.boolean()
56-
}
57-
}
44+
handler: resources.bootstrap.rm.handler
5845
}
5946
})
6047
}

test/cli/test-bootstrap.js

+19-4
Original file line numberDiff line numberDiff line change
@@ -34,28 +34,43 @@ describe('bootstrap', () => {
3434
'/ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD'
3535
]
3636

37+
it('add default', () => {
38+
return ipfs('bootstrap add --default').then((out) => {
39+
expect(out).to.be.eql(defaultList.join('\n'))
40+
})
41+
})
42+
3743
it('list the bootstrap nodes', () => {
3844
return ipfs('bootstrap list').then((out) => {
3945
expect(out).to.eql(defaultList.join('\n'))
4046
})
4147
})
4248

43-
// TODO need https://github.com/ipfs/interface-ipfs-core/issues/97
44-
// to happen, otherwise it is a cat an mouse game
45-
it.skip('add another bootstrap node', () => {
49+
it('add another bootstrap node', () => {
4650
return ipfs('bootstrap add /ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD').then((out) => {
51+
expect(out).to.be.eql('/ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD')
4752
return ipfs('bootstrap list')
4853
}).then((out) => {
4954
expect(out).to.be.eql(updatedList.join('\n'))
5055
})
5156
})
5257

53-
it.skip('rm a bootstrap node', () => {
58+
it('rm a bootstrap node', () => {
5459
return ipfs('bootstrap rm /ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD').then((out) => {
60+
expect(out).to.be.eql('/ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD')
5561
return ipfs('bootstrap list')
5662
}).then((out) => {
5763
expect(out).to.deep.equal(defaultList.join('\n'))
5864
})
5965
})
66+
67+
it('rm all bootstrap nodes', () => {
68+
return ipfs('bootstrap rm --all').then((out) => {
69+
expect(out).to.be.eql('')
70+
return ipfs('bootstrap list')
71+
}).then((out) => {
72+
expect(out).to.deep.equal('')
73+
})
74+
})
6075
})
6176
})

0 commit comments

Comments
 (0)