Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix non-disposable and normalises behaviour #379

Merged
merged 11 commits into from
Sep 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .aegir.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const createServer = require('./src').createServer

const server = createServer() // using defaults
module.exports = {
bundlesize: { maxSize: '281kB' },
bundlesize: { maxSize: '256kB' },
karma: {
files: [{
pattern: 'test/fixtures/**/*',
Expand Down
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ os:
- osx
- windows

script: npx nyc -s npm run test:node -- --bail
script: npx nyc -s npm run test:node -- --bail --timeout 30000
after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov

jobs:
Expand All @@ -31,14 +31,14 @@ jobs:
addons:
chrome: stable
script:
- npx aegir test -t browser -t webworker
- npx aegir test -t browser -t webworker --bail --timeout 30000

- stage: test
name: firefox
addons:
firefox: latest
script:
- npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless
- npx aegir test -t browser -t webworker --bail --timeout 30000 -- --browsers FirefoxHeadless

notifications:
email: false
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ await server.stop()
`ipfsd-ctl` can spawn `disposable` and `non-disposable` daemons.

- `disposable`- Creates on a temporary repo which will be optionally initialized and started (the default), as well cleaned up on process exit. Great for tests.
- `non-disposable` - Requires the user to initialize and start the node, as well as stop and cleanup after wards. Additionally, a non-disposable will allow you to pass a custom repo using the `repoPath` option, if the `repoPath` is not defined, it will use the default repo for the node type (`$HOME/.ipfs` or `$HOME/.jsipfs`). The `repoPath` parameter is ignored for disposable nodes, as there is a risk of deleting a live repo.
- `non-disposable` - Non disposable daemons will by default attach to any nodes running on the default or the supplied repo. Requires the user to initialize and start the node, as well as stop and cleanup afterwards. Additionally, a non-disposable will allow you to pass a custom repo using the `repoPath` option, if the `repoPath` is not defined, it will use the default repo for the node type (`$HOME/.ipfs` or `$HOME/.jsipfs`). The `repoPath` parameter is ignored for disposable nodes, as there is a risk of deleting a live repo.

## Batteries not included. Bring your own IPFS executable.

Expand Down
11 changes: 4 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,18 @@
"@hapi/hapi": "^18.3.2",
"@hapi/joi": "^15.1.1",
"debug": "^4.1.1",
"dexie": "^2.0.4",
"execa": "^2.0.4",
"fs-extra": "^8.1.0",
"hat": "~0.0.3",
"ipfs-http-client": "^36.0.0",
"ipfs-http-client": "^37.0.1",
"ipfs-utils": "^0.3.0",
"lodash.clone": "^4.5.0",
"lodash.defaults": "^4.2.0",
"lodash.defaultsdeep": "^4.6.1",
"multiaddr": "^7.1.0",
"merge-options": "^1.0.1",
"multiaddr": "^7.0.0",
achingbrain marked this conversation as resolved.
Show resolved Hide resolved
"safe-json-stringify": "^1.2.0",
"superagent": "^5.0.5"
},
"devDependencies": {
"aegir": "^20.1.0",
"aegir": "^20.2.0",
"chai": "^4.2.0",
"delay": "^4.3.0",
"detect-port": "^1.3.0",
Expand Down
6 changes: 0 additions & 6 deletions src/defaults/options.json

This file was deleted.

56 changes: 23 additions & 33 deletions src/endpoint/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const hat = require('hat')
const Joi = require('@hapi/joi')
const boom = require('@hapi/boom')
const defaults = require('lodash.defaultsdeep')
const merge = require('merge-options')
const FactoryDaemon = require('../factory-daemon')
const tmpDir = require('../utils/tmp-dir')

Expand All @@ -27,11 +27,13 @@ module.exports = (server) => {
server.route({
method: 'GET',
path: '/util/tmp-dir',
handler: (request) => {
handler: async (request) => {
const type = request.query.type || 'go'
const path = tmpDir(type === 'js')

return { tmpDir: path }
try {
return { tmpDir: await tmpDir(type === 'js') }
} catch (err) {
throw boom.badRequest(err.message)
}
}
})

Expand Down Expand Up @@ -68,28 +70,18 @@ module.exports = (server) => {
const f = new FactoryDaemon({ type: payload.type })

try {
const ipfsd = await f.spawn(payload.options)
const ipfsd = await f.spawn(payload)
const id = hat()
const initialized = ipfsd.initialized
nodes[id] = ipfsd

let api = null

if (nodes[id].started) {
api = {
apiAddr: nodes[id].apiAddr
? nodes[id].apiAddr.toString()
: '',
gatewayAddr: nodes[id].gatewayAddr
? nodes[id].gatewayAddr.toString()
: ''
}
}

return {
id,
api,
initialized
_id: id,
apiAddr: ipfsd.apiAddr ? ipfsd.apiAddr.toString() : '',
gatewayAddr: ipfsd.gatewayAddr ? ipfsd.gatewayAddr.toString() : '',
initialized: ipfsd.initialized,
started: ipfsd.started,
_env: ipfsd._env,
path: ipfsd.path
}
} catch (err) {
throw boom.badRequest(err.message)
Expand Down Expand Up @@ -135,10 +127,8 @@ module.exports = (server) => {
await nodes[id].start(flags)

return {
api: {
apiAddr: nodes[id].apiAddr.toString(),
gatewayAddr: nodes[id].gatewayAddr.toString()
}
apiAddr: nodes[id].apiAddr.toString(),
gatewayAddr: nodes[id].gatewayAddr ? nodes[id].gatewayAddr.toString() : ''
}
} catch (err) {
throw boom.badRequest(err.message)
Expand Down Expand Up @@ -206,7 +196,7 @@ module.exports = (server) => {
path: '/stop',
handler: async (request, h) => {
const id = request.query.id
const timeout = request.payload.timeout
const timeout = request.payload && request.payload.timeout

try {
await nodes[id].stop(timeout)
Expand All @@ -230,7 +220,7 @@ module.exports = (server) => {
path: '/kill',
handler: async (request, h) => {
const id = request.query.id
const timeout = request.payload.timeout
const timeout = request.payload && request.payload.timeout

try {
await nodes[id].killProcess(timeout)
Expand Down Expand Up @@ -277,13 +267,13 @@ module.exports = (server) => {
throw boom.badRequest(err.message)
}
},
config: defaults({}, {
config: merge(routeConfig, {
validate: {
query: {
key: Joi.string().optional()
}
}
}, routeConfig)
})
})

/*
Expand All @@ -305,13 +295,13 @@ module.exports = (server) => {

return h.response().code(200)
},
config: defaults({}, {
config: merge(routeConfig, {
validate: {
payload: {
key: Joi.string(),
value: Joi.any()
}
}
}, routeConfig)
})
})
}
33 changes: 23 additions & 10 deletions src/factory-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

const request = require('superagent')
const DaemonClient = require('./ipfsd-client')
const merge = require('merge-options')
const defaultConfig = require('./defaults/config.json')

/** @ignore @typedef {import("./index").SpawnOptions} SpawnOptions */

Expand All @@ -23,7 +25,7 @@ class FactoryClient {
this.options = options

if (options.type === 'proc') {
throw new Error(`'proc' is not supported in client mode`)
throw new Error('\'proc\' is not supported in client mode')
}

this.baseUrl = `${options.secure ? 'https://' : 'http://'}${options.host}:${options.port}`
Expand All @@ -33,12 +35,14 @@ class FactoryClient {
* Utility method to get a temporary directory
* useful in browsers to be able to generate temp
* repos manually
* @param {boolean} isJS
*
* @returns {Promise}
*/
async tmpDir () {
async tmpDir (isJS) {
const res = await request
.get(`${this.baseUrl}/util/tmp-dir`)
.query({ type: isJS ? 'js' : 'go' })

return res.body.tmpDir
}
Expand Down Expand Up @@ -66,19 +70,28 @@ class FactoryClient {
* @return {Promise}
*/
async spawn (options = {}) {
const daemonOptions = merge({
exec: this.options.exec,
type: this.options.type,
IpfsClient: this.options.IpfsClient,
disposable: true,
start: options.disposable !== false,
init: options.disposable !== false,
config: defaultConfig
}, options)

if (options.defaultAddrs) {
delete daemonOptions.config.Addresses
}

const res = await request
.post(`${this.baseUrl}/spawn`)
.send({ options: options, type: this.options.type })
const apiAddr = res.body.api ? res.body.api.apiAddr : ''
const gatewayAddr = res.body.api ? res.body.api.gatewayAddr : ''
.send(daemonOptions)

const ipfsd = new DaemonClient(
this.baseUrl,
res.body.id,
res.body.initialized,
apiAddr,
gatewayAddr,
{ IpfsClient: this.options.IpfsClient }
res.body,
daemonOptions
)

return ipfsd
Expand Down
67 changes: 19 additions & 48 deletions src/factory-daemon.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
'use strict'

const defaultsDeep = require('lodash.defaultsdeep')
const clone = require('lodash.clone')
const path = require('path')
const tmpDir = require('./utils/tmp-dir')
const Daemon = require('./ipfsd-daemon')
const merge = require('merge-options')
const defaultConfig = require('./defaults/config.json')
const defaultOptions = require('./defaults/options.json')

/** @ignore @typedef {import("./index").SpawnOptions} SpawnOptions */

Expand All @@ -22,7 +19,7 @@ class FactoryDaemon {
if (options && options.type === 'proc') {
throw new Error('This Factory does not know how to spawn in proc nodes')
}
this.options = Object.assign({}, { type: 'go' }, options)
this.options = merge({ type: 'go' }, options)
}

/**
Expand All @@ -36,7 +33,7 @@ class FactoryDaemon {
* @returns {Promise}
*/
tmpDir (type) {
return tmpDir(type === 'js')
return Promise.resolve(tmpDir(type === 'js'))
}

/**
Expand Down Expand Up @@ -68,57 +65,31 @@ class FactoryDaemon {
* Spawn an IPFS node, either js-ipfs or go-ipfs
*
* @param {SpawnOptions} [options={}] - Various config options and ipfs config parameters
* @param {function(Error, Daemon): void} callback - Callback receives Error or a Daemon instance, Daemon has a `api` property which is an `ipfs-http-client` instance.
* @returns {void}
* @returns {Promise<Daemon>}
*/
async spawn (options = {}) {
// TODO this options parsing is daunting. Refactor and move to a separate
// func documenting what it is trying to do.
options = defaultsDeep(
{ IpfsClient: this.options.IpfsClient },
options,
defaultOptions
)

options.init = typeof options.init !== 'undefined'
? options.init
: true

if (!options.disposable) {
const nonDisposableConfig = clone(defaultConfig)
options.init = false
options.start = false

const defaultRepo = path.join(
process.env.HOME || process.env.USERPROFILE,
options.isJs
? '.jsipfs'
: '.ipfs'
)

options.repoPath = options.repoPath ||
(process.env.IPFS_PATH || defaultRepo)
options.config = defaultsDeep({}, options.config, nonDisposableConfig)
} else {
options.config = defaultsDeep({}, options.config, defaultConfig)
}
const daemonOptions = merge({
exec: this.options.exec,
type: this.options.type,
IpfsClient: this.options.IpfsClient,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish this was just client

Copy link
Member

@achingbrain achingbrain Sep 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not actionable feedback, please ignore.

disposable: true,
start: options.disposable !== false,
init: options.disposable !== false,
config: defaultConfig
}, options)

if (options.defaultAddrs) {
delete options.config.Addresses
delete daemonOptions.config.Addresses
}

options.type = this.options.type
options.exec = options.exec || this.options.exec
options.initOptions = defaultsDeep({}, this.options.initOptions, options.initOptions)

const node = new Daemon(options)
const node = new Daemon(daemonOptions)

if (options.init) {
await node.init(options.initOptions)
if (daemonOptions.init) {
await node.init(daemonOptions.initOptions)
}

if (options.start) {
await node.start(options.args)
if (daemonOptions.start) {
await node.start(daemonOptions.args)
}

return node
Expand Down
Loading