Skip to content

Commit

Permalink
Fix ipfs start detached flag
Browse files Browse the repository at this point in the history
  • Loading branch information
kernelwhisperer committed Nov 23, 2019
1 parent 8dc2c36 commit 6530be3
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 161 deletions.
98 changes: 43 additions & 55 deletions packages/aragon-cli/src/commands/ipfs_cmds/start.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
// import path from 'path'
import TaskList from 'listr'
// import chalk from 'chalk'
// import IPFS from 'ipfs-api'
import listrOpts from '@aragon/cli-utils/src/helpers/listr-options'
//
import {
startDaemon,
// isIPFSCORS,
// setIPFSCORS as setCORS,
// isIPFSRunning,
getDefaultRepoPath,
setPorts,
// getClient,
ensureIPFSInitialized,
getClient,
setIPFSCORS,
pinArtifacts,
} from '../../lib/ipfs'

export const command = 'start'
Expand All @@ -35,7 +32,8 @@ export const builder = yargs =>
})
.option('detached', {
description: 'Whether to run the daemon in the background',
default: true,
alias: 'd',
default: false,
boolean: true,
})

Expand All @@ -51,51 +49,27 @@ const runStartTask = ({
return new TaskList(
[
{
title: 'Configure ports',
title: 'Checking repository',
task: async () => {
await setPorts(repoPath, apiPort, gatewayPort, swarmPort)
await ensureIPFSInitialized(repoPath)
},
},
{
title: 'Configure ports',
task: async ctx => {
try {
await setPorts(repoPath, apiPort, gatewayPort, swarmPort)
} catch (e) {
ctx.setPortsSuccess = false
}
},
},
{
title: 'Start the daemon',
task: async () => {
await startDaemon(repoPath, { detached })
task: async ctx => {
ctx.processController = await startDaemon(repoPath, { detached })
},
},
// {
// title: 'Connect to the API',
// task: async (ctx) => {
// ctx.apiClient = await getClient(`http://localhost:${apiPort}`)
// },
// },
// {
// title: 'Configure CORS',
// task: async (ctx) => {
// await setCORS(ctx.apiClient)
// }
// },
// {
// title: 'Pin the latest aragon artifacts',
// task: ctx => {
// await pinLatestArtifacts(ctx.apiClient)
// const ipfs = IPFS('localhost', '5001', { protocol: 'http' })
// const files = path.resolve(
// require.resolve('@aragon/aragen'),
// '../ipfs-cache'
// )

// return new Promise((resolve, reject) => {
// ipfs.util.addFromFs(
// files,
// { recursive: true, ignore: 'node_modules' },
// (err, files) => {
// if (err) return reject(err)
// resolve(files)
// }
// )
// })
// },
// },
],
listrOpts(silent, debug)
).run()
Expand All @@ -110,9 +84,10 @@ export const handler = async argv => {
gatewayPort,
swarmPort,
repoPath,
reporter,
} = argv

await runStartTask({
const { processController } = await runStartTask({
detached,
apiPort,
gatewayPort,
Expand All @@ -122,12 +97,25 @@ export const handler = async argv => {
repoPath,
})

// if (ctx.started) {
// reporter.info(
// 'IPFS daemon is now running. Stopping this process will stop IPFS'
// )
// } else {
// reporter.warning(chalk.yellow("Didn't start IPFS, port busy"))
// process.exit()
// }
reporter.info(`Daemon output:\n${processController.output}`)

if (detached) {
processController.detach()
reporter.warning('The IPFS Daemon will continue running in the background!')
reporter.warning('Use the `aragon ipfs stop` command to stop it.')
} else {
processController.attach()
reporter.info(
'Did you know you can run the IPFS Daemon in the background using the `-d` flag?'
)
}

/**
* Configure IPFS with Aragon-specific logic
*/
const apiClient = await getClient(`http://localhost:${apiPort}`)
await setIPFSCORS(apiClient)
reporter.success('Successfully configured CORS')
const hashes = await pinArtifacts(apiClient)
reporter.success(`Successfully pinned ${hashes.length} Aragon artifacts.`)
}
6 changes: 6 additions & 0 deletions packages/aragon-cli/src/lib/ipfs/aragon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import path from 'path'

export const pinArtifacts = async apiClient => {
const files = path.resolve(require.resolve('@aragon/aragen'), '../ipfs-cache')
return apiClient.addFromFs(files, { recursive: true, ignore: 'node_modules' })
}
12 changes: 8 additions & 4 deletions packages/aragon-cli/src/lib/ipfs/config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { join as joinPath } from 'path'
import path, { join as joinPath } from 'path'
import oldIpfsAPI from 'ipfs-api'
import { readJson, writeJson } from 'fs-extra'
import getFolderSize from 'get-folder-size'
Expand Down Expand Up @@ -43,16 +43,20 @@ const IPFSCORS = [
},
]

export const ensureIPFSInitialized = async () => {
export const ensureIPFSInitialized = async repoPath => {
if (!getBinary('ipfs')) {
throw new Error(
'IPFS is not installed. Use `aragon ipfs install` before proceeding.'
)
}

if (!existsSync(getDefaultRepoPath())) {
if (!existsSync(path.resolve(repoPath))) {
// We could use 'ipfs daemon --init' when https://github.com/ipfs/go-ipfs/issues/3913 is solved
await execa(getBinary('ipfs'), ['init'])
await execa(getBinary('ipfs'), ['init'], {
env: {
IPFS_PATH: repoPath,
},
})
}
}

Expand Down
107 changes: 13 additions & 94 deletions packages/aragon-cli/src/lib/ipfs/daemon.js
Original file line number Diff line number Diff line change
@@ -1,99 +1,9 @@
import execa from 'execa'
import { getBinary, isPortTaken } from '../../util'
import oldIpfsAPI from 'ipfs-api'
import { IPFS_START_TIMEOUT } from './constants'
import { connectOrThrow } from './misc'
import { startProcess } from '../node'

let ipfsNode

export const isIPFSRunning = async ipfsRpc => {
const portTaken = await isPortTaken(ipfsRpc.port)

if (portTaken) {
if (!ipfsNode) ipfsNode = oldIpfsAPI(ipfsRpc)

try {
// if port is taken, attempt to fetch the node id
// if this errors, we can assume the port is taken
// by a process other then the ipfs gateway
await ipfsNode.id()
return true
} catch (e) {
return false
}
}

return false
}
export const startIPFSDaemon = () => {
if (!getBinary('ipfs')) {
throw new Error(
'IPFS is not installed. Use `aragon ipfs install` before proceeding.'
)
}

let startOutput = ''

// We add a timeout as starting
const timeout = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error(`Starting IPFS timed out:\n${startOutput}`))
}, IPFS_START_TIMEOUT)
})

const start = new Promise((resolve, reject) => {
// await ensureIPFSInitialized()
const ipfsProc = execa(getBinary('ipfs'), ['daemon', '--migrate'])

ipfsProc.stdout.on('data', data => {
startOutput = `${startOutput}${data.toString()}\n`
if (data.toString().includes('Daemon is ready')) resolve()
})

ipfsProc.stderr.on('data', data => {
reject(new Error(`Starting IPFS failed: ${data.toString()}`))
})
})

return Promise.race([start, timeout])
}

export const startDetachedProcess = async ({
cmd,
args,
execaOpts,
readyOutput,
}) => {
return new Promise((resolve, reject) => {
// start the process
const subprocess = execa(
cmd,
args,
Object.assign({ detached: true }, execaOpts)
)

subprocess.stderr.on('data', data => {
// parse
data = data.toString()
reject(new Error(data))
})

subprocess.stdout.on('data', data => {
// parse
data = data.toString()
// check for ready signal
if (data.includes(readyOutput)) {
resolve()
// prevent the parent from waiting on this subprocess
subprocess.stderr.destroy()
subprocess.stdout.destroy()
subprocess.unref()
}
})
})
}

export const startDaemon = async (repoPath, options) => {
export const startDaemon = (repoPath, options = {}) => {
const ipfsBinary = getBinary('ipfs')

if (!ipfsBinary) {
Expand All @@ -102,11 +12,20 @@ export const startDaemon = async (repoPath, options) => {
)
}

await startDetachedProcess({
const processSetup = {
detached: options.detached,
cmd: ipfsBinary,
args: ['daemon', '--migrate'],
execaOpts: {
env: {
IPFS_PATH: repoPath,
},
},
readyOutput: 'Daemon is ready',
})
timeout: IPFS_START_TIMEOUT,
}

return startProcess(processSetup)
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/aragon-cli/src/lib/ipfs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './data-viz'
export * from './propagation'
export * from './misc'
export * from './validation'
export * from './aragon'
8 changes: 0 additions & 8 deletions packages/aragon-cli/src/lib/ipfs/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,6 @@ export function parseAddressAsURL(address) {
}
}

// function timeout() {
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// reject(FETCH_TIMEOUT_ERR)
// }, FETCH_TIMEOUT)
// })
// }

export const getGlobalNpmPrefix = async () =>
(await execa('npm', ['prefix', '--global'])).stdout

Expand Down
2 changes: 2 additions & 0 deletions packages/aragon-cli/src/lib/node/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './process'
export * from './misc'
20 changes: 20 additions & 0 deletions packages/aragon-cli/src/lib/node/misc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* If we don't use `clearTimeout` the process will stay alive
* until the timeout has been processed: <https://nodejs.org/api/timers.html#timers_class_timeout>
*/
export const withTimeout = async (promise, timeout, error) => {
let timeoutObject

const timeoutPromise = new Promise((resolve, reject) => {
timeoutObject = setTimeout(() => {
reject(error)
}, timeout)
})

await Promise.race([promise, timeoutPromise])

clearTimeout(timeoutObject)

// return the initial promise object
return promise
}
Loading

0 comments on commit 6530be3

Please sign in to comment.