Skip to content

Commit

Permalink
feat(start): implement agoric start testnet
Browse files Browse the repository at this point in the history
Both docker install and `--sdk` install are supported.
  • Loading branch information
michaelfig committed Feb 6, 2020
1 parent f4cce4f commit cbfb306
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 16 deletions.
2 changes: 2 additions & 0 deletions packages/agoric-cli/bin/agoric
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const chalk = esmRequire('chalk').default;
const WebSocket = esmRequire('ws');
const { spawn } = esmRequire('child_process');
const fs = esmRequire('fs').promises;
const os = esmRequire('os');

const main = esmRequire('../lib/main.js').default;
const progname = path.basename(process.argv[1]);
Expand All @@ -23,6 +24,7 @@ main(progname, rawArgs, {
error,
makeWebSocket,
fs,
os,
process,
spawn,
}).then(
Expand Down
127 changes: 115 additions & 12 deletions packages/agoric-cli/lib/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ import parseArgs from 'minimist';
import path from 'path';
import chalk from 'chalk';

const FAKE_CHAIN_DELAY = 5;
const FAKE_CHAIN_DELAY =
process.env.FAKE_CHAIN_DELAY === undefined
? 5
: Number(process.env.FAKE_CHAIN_DELAY);
const PORT = process.env.PORT || 8000;
const HOST_PORT = process.env.HOST_PORT || PORT;

export default async function startMain(progname, rawArgs, priv, opts) {
const { console, error, fs, spawn, process } = priv;
const { console, error, fs, spawn, os, process } = priv;
const { reset, _: args } = parseArgs(rawArgs, {
boolean: ['reset'],
});
Expand Down Expand Up @@ -40,17 +45,22 @@ export default async function startMain(progname, rawArgs, priv, opts) {
};

let agSolo;
let agSetupSolo;
let agServer;
if (opts.sdk) {
agSolo = path.resolve(__dirname, '../../cosmic-swingset/bin/ag-solo');
agSetupSolo = path.resolve(__dirname, '../../cosmic-swingset/setup-solo');
} else {
if (!(await exists('.agservers/node_modules'))) {
return error(`you must first run '${progname} install'`);
}
agSolo = `${process.cwd()}/node_modules/@agoric/cosmic-swingset/bin/ag-solo`;
}

async function startDev(profileName) {
async function startFakeChain(profileName) {
if (!opts.sdk) {
if (!(await exists('.agservers/node_modules'))) {
return error(`you must first run '${progname} install'`);
}
}

const fakeGCI = 'myFakeGCI';
if (!(await exists(agServer))) {
console.log(chalk.yellow(`initializing ${profileName}`));
Expand Down Expand Up @@ -78,19 +88,112 @@ export default async function startMain(progname, rawArgs, priv, opts) {
);
await linkHtml(profileName);

await pspawn(agSolo, ['start', '--role=two_client'], {
return pspawn(agSolo, ['start', '--role=two_client'], {
stdio: 'inherit',
cwd: agServer,
});
}

async function startTestnet(profileName) {
async function startTestnetDocker(profileName, startArgs) {
const IMAGE = `agoric/cosmic-swingset-setup-solo`;

if (startArgs[0] === '--pull') {
startArgs.shift();
await pspawn('docker', ['pull', IMAGE], {
stdio: 'inherit',
});
}

const setupRun = (...bonusArgs) =>
pspawn(
'docker',
[
'run',
`-p127.0.0.1:${HOST_PORT}:${PORT}`,
`--volume=${process.cwd()}:/usr/src/dapp`,
`-eAG_SOLO_BASEDIR=/usr/src/dapp/.agservers/${profileName}`,
`--rm`,
`-it`,
IMAGE,
`--webport=${PORT}`,
`--webhost=0.0.0.0`,
...bonusArgs,
...startArgs,
],
{
stdio: 'inherit',
},
);

if (!(await exists(agServer))) {
const status =
(await setupRun('--no-restart')) || (await linkHtml(profileName));
if (status) {
return status;
}
}

return setupRun();
}

async function startTestnetSdk(profileName, startArgs) {
const virtEnv = path.resolve(
`.agservers/ve3-${os.platform()}-${os.arch()}`,
);
if (!(await exists(`${virtEnv}/bin/pip`))) {
const status = await pspawn('python3', ['-mvenv', virtEnv], {
stdio: 'inherit',
cwd: agSetupSolo,
});
if (status) {
return status;
}
}

const pipRun = (...bonusArgs) =>
pspawn(`${virtEnv}/bin/pip`, bonusArgs, {
stdio: 'inherit',
cwd: agSetupSolo,
});

if (!(await exists(`${virtEnv}/bin/wheel`))) {
const status = await pipRun('install', 'wheel');
if (status) {
return status;
}
}

if (!(await exists(`${virtEnv}/bin/ag-setup-solo`))) {
const status = await pipRun('install', `--editable`, '.');
if (status) {
return status;
}
}

const setupRun = (...bonusArgs) =>
pspawn(
`${virtEnv}/bin/ag-setup-solo`,
[`--webport=${PORT}`, ...bonusArgs, ...startArgs],
{
stdio: 'inherit',
env: { ...process.env, AG_SOLO_BASEDIR: agServer },
},
);

if (!(await exists(agServer))) {
const status =
(await setupRun('--no-restart')) || (await linkHtml(profileName));
if (status) {
return status;
}
}

return setupRun();
}

const profiles = {
dev: startDev,
testnet: startTestnet,
dev: startFakeChain,
testnet: opts.sdk ? startTestnetSdk : startTestnetDocker,
};

const profileName = args[0] || 'dev';
Expand All @@ -108,9 +211,9 @@ export default async function startMain(progname, rawArgs, priv, opts) {
agServer = `.agservers/${profileName}`;
if (reset) {
console.log(chalk.green(`removing ${agServer}`));
// FIXME: Use portable rimraf.
// rm is available on all the unix-likes, so use it for speed.
await pspawn('rm', ['-rf', agServer], { stdio: 'inherit' });
}

await startFn(profileName, agServer);
return startFn(profileName, args[0] ? args.slice(1) : args);
}
1 change: 1 addition & 0 deletions packages/agoric-cli/template/.agservers/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,4 @@ integration-test/transform-tests/output
/dev
/testnet
/chain
/ve*
11 changes: 7 additions & 4 deletions packages/cosmic-swingset/setup-solo/src/ag_setup_solo/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Options(usage.Options):
]
optFlags = [
["destroy", None, "destroy all chain state"],
["no-restart", None, "do not restart the solo vat"],
]
def parseArgs(self, basedir=os.environ.get('AG_SOLO_BASEDIR', 'agoric')):
self['basedir'] = os.environ['AG_SOLO_BASEDIR'] = basedir
Expand All @@ -46,7 +47,9 @@ def parseArgs(self, basedir=os.environ.get('AG_SOLO_BASEDIR', 'agoric')):
def setIngress(sm):
print('Setting chain parameters with ' + AG_SOLO)
subprocess.run([AG_SOLO, 'set-gci-ingress', '--chainID=%s' % sm['chainName'], sm['gci'], *sm['rpcAddrs']], check=True)
def restart():
def restart(o):
if o['no-restart']:
return
print('Restarting ' + AG_SOLO)
os.execvp(AG_SOLO, [AG_SOLO, 'start', '--role=client'])

Expand Down Expand Up @@ -95,7 +98,7 @@ def cleanup():
except:
cleanup()
raise
restart()
restart(o)

def doInit(o):
BASEDIR = o['basedir']
Expand Down Expand Up @@ -123,7 +126,7 @@ def resetNetconfig(o):
for conn in conns:
if 'GCI' in conn and conn['GCI'] == netconfig['gci']:
print('Already have an entry for ' + conn['GCI'] + '; not replacing')
restart()
restart(o)
sys.exit(1)

return netconfig
Expand Down Expand Up @@ -169,5 +172,5 @@ def main():
doInit(o)

setIngress(netconfig)
restart()
restart(o)
sys.exit(1)

0 comments on commit cbfb306

Please sign in to comment.