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

Commit

Permalink
feat: allow daemon to init and start in a single cmd
Browse files Browse the repository at this point in the history
This PR aligns `ipfs init` and `ipfs daemon` with go-ipfs.

ipfs/kubo#6489

`ipfs init` changed to accept a file path as an argument

`ipfs daemon` changed to support `--init` and `--init-config` options.

Now we can do `ipfs daemon --init --init-config /path/to/custom-config`

refs:
ipfs/js-ipfsd-ctl#303
  • Loading branch information
hugomrdias committed Sep 11, 2019
1 parent 30768b0 commit c207cc2
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 15 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@
"qs": "^6.5.2",
"rimraf": "^3.0.0",
"sinon": "^7.4.2",
"stream-to-promise": "^2.2.0"
"stream-to-promise": "^2.2.0",
"temp-write": "^4.0.0"
},
"optionalDependencies": {
"prom-client": "^11.5.3",
Expand Down
25 changes: 25 additions & 0 deletions src/cli/commands/daemon.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use strict'

const os = require('os')
const fs = require('fs')
const toUri = require('multiaddr-to-uri')
const { ipfsPathHelp } = require('../utils')
const { isTest } = require('ipfs-utils/src/env')
const debug = require('debug')('ipfs:cli:daemon')

module.exports = {
command: 'daemon',
Expand All @@ -13,6 +15,15 @@ module.exports = {
builder (yargs) {
return yargs
.epilog(ipfsPathHelp)
.option('init', {
type: 'boolean',
default: false,
desc: 'Initialize ipfs with default settings if not already initialized.'
})
.option('init-config', {
type: 'string',
desc: 'Path to existing configuration file to be loaded during --init.'
})
.option('enable-sharding-experiment', {
type: 'boolean',
default: false
Expand Down Expand Up @@ -42,9 +53,23 @@ module.exports = {

const repoPath = argv.getRepoPath()

let config = {}
// read and parse config file
if (argv.initConfig) {
try {
const raw = fs.readFileSync(argv.initConfig)
config = JSON.parse(raw)
} catch (error) {
debug(error)
throw new Error('Default config couldn\'t be found or content isn\'t valid JSON.')
}
}

// Required inline to reduce startup time
const Daemon = require('../../cli/daemon')
const daemon = new Daemon({
init: argv.init,
config,
silent: argv.silent,
repo: process.env.IPFS_PATH,
offline: argv.offline,
Expand Down
22 changes: 18 additions & 4 deletions src/cli/commands/init.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
'use strict'

const fs = require('fs')
const debug = require('debug')('ipfs:cli:init')
const { ipfsPathHelp } = require('../utils')

module.exports = {
command: 'init [config] [options]',
command: 'init [default-config] [options]',
describe: 'Initialize a local IPFS node',
builder (yargs) {
return yargs
.epilog(ipfsPathHelp)
.positional('config', {
describe: 'Node config, this should JSON and will be merged with the default config. Check https://github.com/ipfs/js-ipfs#optionsconfig',
.positional('default-config', {
describe: 'Initialize with the given configuration. Path to the config file. Check https://github.com/ipfs/js-ipfs#optionsconfig',
type: 'string'
})
.option('bits', {
Expand All @@ -34,6 +36,18 @@ module.exports = {
argv.resolve((async () => {
const path = argv.getRepoPath()

let config = {}
// read and parse config file
if (argv.defaultConfig) {
try {
const raw = fs.readFileSync(argv.defaultConfig)
config = JSON.parse(raw)
} catch (error) {
debug(error)
throw new Error('Default config couldn\'t be found or content isn\'t valid JSON.')
}
}

argv.print(`initializing ipfs node at ${path}`)

// Required inline to reduce startup time
Expand All @@ -44,7 +58,7 @@ module.exports = {
repo: new Repo(path),
init: false,
start: false,
config: argv.config || {}
config
})

try {
Expand Down
2 changes: 1 addition & 1 deletion src/cli/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Daemon {
}

// start the daemon
const ipfsOpts = Object.assign({ init: false }, this._options, { start: true, libp2p })
const ipfsOpts = Object.assign({ }, this._options, { start: true, libp2p })
const ipfs = new IPFS(ipfsOpts)

await new Promise((resolve, reject) => {
Expand Down
49 changes: 49 additions & 0 deletions test/cli/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,29 @@ const os = require('os')
const path = require('path')
const hat = require('hat')
const fs = require('fs')
const tempWrite = require('temp-write')
const pkg = require('../../package.json')

const skipOnWindows = isWindows() ? it.skip : it
const daemonReady = (daemon, fn) => {
let r = null
const p = new Promise((resolve, reject) => {
daemon.stdout.on('data', async (data) => {
if (data.toString().includes('Daemon is ready')) {
try {
r = await fn()
} catch (err) {
reject(err)
}
daemon.kill()
}
})
daemon.stderr.on('data', () => reject(new Error('Daemon didnt start')))
daemon.then(() => resolve(r)).catch(reject)
})

return p
}
const checkLock = (repo) => {
// skip on windows
// https://github.com/ipfs/js-ipfsd-ctl/pull/155#issuecomment-326983530
Expand Down Expand Up @@ -265,4 +284,34 @@ describe('daemon', () => {
expect(err.stdout).to.include(`Node.js version: ${process.versions.node}`)
}
})

it('should init', async function () {
this.timeout(100 * 1000)
const daemon = ipfs('daemon --init')
let stdout = ''

daemon.stdout.on('data', (data) => {
stdout += data.toString('utf8')

if (stdout.includes('Daemon is ready')) {
daemon.kill()
}
})

try {
await daemon
throw new Error('Did not kill process')
} catch (err) {
expect(err.killed).to.be.true()
}
})

it('should init with custom config', async function () {
this.timeout(100 * 1000)
const configPath = tempWrite.sync('{"Addresses": {"API": "/ip4/127.0.0.1/tcp/9999"}}', 'config.json')
const daemon = ipfs(`daemon --init --init-config ${configPath}`)

const r = await daemonReady(daemon, () => ipfs('config \'Addresses.API\''))
expect(r).to.be.eq('/ip4/127.0.0.1/tcp/9999')
})
})
20 changes: 11 additions & 9 deletions test/cli/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ const clean = require('../utils/clean')
const hat = require('hat')
const ipfsExec = require('../utils/ipfs-exec')
const os = require('os')
const tempWrite = require('temp-write')

describe('init', function () {
this.timeout(40 * 1000)
this.timeout(100 * 1000)

let repoPath
let ipfs
Expand All @@ -33,8 +34,6 @@ describe('init', function () {
afterEach(() => clean(repoPath))

it('basic', function () {
this.timeout(40 * 1000)

return ipfs('init').then((out) => {
expect(repoDirSync('blocks')).to.have.length.above(2)
expect(repoExistsSync('config')).to.equal(true)
Expand All @@ -48,8 +47,6 @@ describe('init', function () {
})

it('bits', function () {
this.timeout(40 * 1000)

return ipfs('init --bits 1024').then(() => {
expect(repoDirSync('blocks')).to.have.length.above(2)
expect(repoExistsSync('config')).to.equal(true)
Expand All @@ -58,8 +55,6 @@ describe('init', function () {
})

it('empty', function () {
this.timeout(40 * 1000)

return ipfs('init --bits 1024 --empty-repo true').then(() => {
expect(repoDirSync('blocks')).to.have.length(2)
expect(repoExistsSync('config')).to.equal(true)
Expand All @@ -68,11 +63,18 @@ describe('init', function () {
})

it('should present ipfs path help when option help is received', function (done) {
this.timeout(100 * 1000)

ipfs('init --help').then((res) => {
expect(res).to.have.string('export IPFS_PATH=/path/to/ipfsrepo')
done()
})
})

it('default config argument', () => {
const configPath = tempWrite.sync('{"Addresses": {"API": "/ip4/127.0.0.1/tcp/9999"}}', 'config.json')
return ipfs(`init ${configPath}`).then((res) => {
const configRaw = fs.readFileSync(path.join(repoPath, 'config')).toString()
const config = JSON.parse(configRaw)
expect(config.Addresses.API).to.be.eq('/ip4/127.0.0.1/tcp/99999')
})
})
})

0 comments on commit c207cc2

Please sign in to comment.