added repl to wskdb
diff --git a/nodejs/client/lib/repl.js b/nodejs/client/lib/repl.js
new file mode 100644
index 0000000..06a3b82
--- /dev/null
+++ b/nodejs/client/lib/repl.js
@@ -0,0 +1,89 @@
+var prompt = require('inquirer'),
+ rewriter = require('./rewriter');
+
+var help = {
+ handler: function help() {
+ console.log('The available commands are:');
+ console.log();
+
+ var grouped = {};
+ for (var x in commandHandlers) {
+ var already = grouped[commandHandlers[x].description];
+ if (already) {
+ grouped[commandHandlers[x].description] = already + ", " + x;
+ } else {
+ grouped[commandHandlers[x].description] = x;
+ }
+ }
+
+ var pruned = [];
+ for (var d in grouped) {
+ pruned.push({ command: grouped[d], description: d });
+ }
+
+ console.log(columnify(pruned, { minWidth: 18 }));
+ },
+ description: "Print this help text"
+};
+var attach = {
+ handler: rewriter.attach,
+ description: "Attach to an action",
+ synchronous: true
+};
+var detach = {
+ handler: rewriter.detach,
+ description: "Detatch from an action",
+ synchronous: true
+};
+var exit = {
+ handler: function(wskprops) {
+ //console.log("Cleaning up".red);
+ rewriter.detachAll(wskprops, process.exit);
+ },
+ description: "Quit the debugger"
+};
+var invoke = {
+ handler: rewriter.invoke,
+ description: "Invoke an action",
+ synchronous: true
+};
+
+var commandHandlers = {
+ invoke: invoke,
+ attach: attach,
+ detach: detach,
+ exit: exit,
+ quit: exit,
+ e: exit,
+ q: exit,
+ help: help,
+ h: help,
+ '?': help
+};
+
+function repl(wskprops) {
+ prompt.prompt([{
+ name: 'command', message: '(wskdb)',
+ validate: function(line) {
+ var commandLine = line.split(/\s+/);
+ return commandLine.length > 0 && commandHandlers[commandLine[0]] ? true : "Invalid command";
+ }
+ }]).then(function(response) {
+ var commandLine = response.command.split(/\s+/);
+ var command = commandLine.shift();
+ var handler = commandHandlers[command];
+
+ if (handler.synchronous) {
+ commandLine.unshift(repl.bind(undefined, wskprops));
+ }
+ commandLine.unshift(wskprops);
+
+ handler.handler.apply(undefined, commandLine);
+
+ if (!handler.synchronous) {
+ repl(wskprops);
+ }
+ });
+}
+
+exports.repl = repl;
diff --git a/nodejs/client/lib/rewriter.js b/nodejs/client/lib/rewriter.js
new file mode 100644
index 0000000..c2d5603
--- /dev/null
+++ b/nodejs/client/lib/rewriter.js
@@ -0,0 +1,182 @@
+var uuid = require('uuid'),
+ openwhisk = require('openwhisk'),
+ api = {
+ host: 'https://openwhisk.ng.bluemix.net',
+ path: '/api/v1'
+ };
+
+var attached = {};
+
+var echoCompletion = "function main(params) { return params; }";
+
+function setupOpenWhisk(wskprops) {
+ var key = wskprops['AUTH'];
+ var namespace = wskprops['NAMESPACE'];
+ var ow = openwhisk({
+ api: api.host + api.path,
+ api_key: key,
+ namespace: namespace
+ });
+ return ow;
+}
+
+exports.attach = function attach(wskprops, next, entity) {
+ var names = attached[entity] = {
+ triggerName: uuid.v4(),
+ actionName: uuid.v4(),
+ ruleName: uuid.v4(),
+ action: echoCompletion
+ };
+
+ console.log("Attaching".blue + " to " + entity);
+
+ var ow = setupOpenWhisk(wskprops);
+
+ try {
+ Promise.all([ow.triggers.create(names),
+ ow.actions.create(names)])
+ .then(function() {
+ ow.rules
+ .create({ ruleName: names.ruleName, trigger: names.triggerName, action: names.actionName })
+ .then(next);
+ });
+ } catch (e) {
+ console.error(e);
+ }
+};
+
+exports.detachAll = function detachAll(wskprops, next) {
+ var ow = setupOpenWhisk(wskprops);
+
+ var count = 0;
+ function done() {
+ if (--count <= 0) {
+ next && next();
+ }
+ }
+
+ for (var entity in attached) {
+ count++;
+ }
+
+ if (count == 0) {
+ done();
+ } else {
+ for (var entity in attached) {
+ exports.detach(wskprops, done, entity);
+ }
+ }
+};
+
+exports.detach = function detach(wskprops, next, entity) {
+ console.log("Detaching".blue + " from " + entity);
+
+ function errlog(idx, noNext) {
+ return function(err) {
+ console.error("Error " + idx, err);
+ if (!noNext) next();
+ };
+ }
+
+ var names = attached[entity];
+ if (names) {
+ try {
+ var ow = setupOpenWhisk(wskprops);
+ //console.log("D1");
+ ow.rules.disable(names).then(function() {
+ try {
+ //console.log("D2");
+ Promise.all([ow.triggers.delete(names),
+ ow.actions.delete(names)])
+ .then(function(values) {
+ //console.log("D3");
+ ow.rules.delete(names).then(function() {
+ try { delete attached[entity]; next(); } catch (err) { errlog(5, true)(); }
+ }, errlog(4));
+ }, errlog(3));
+ } catch (err) { errlog(2, true)(); }
+ }, errlog(1));
+ } catch (e) {
+ console.error(e);
+ }
+ }
+};
+
+exports.invoke = function invoke() {
+ try {
+ exports._invoke.apply(undefined, arguments);
+ } catch (e) {
+ console.error(e);
+ }
+};
+exports._invoke = function invoke() {
+ var args = Array.prototype.slice.call(arguments);
+ var wskprops = args.shift();
+ var namespace = wskprops['NAMESPACE'];
+ var next = args.shift();
+ var action = args.shift();
+
+ var params = {};
+ for (var i = 0; i < args.length; i++) {
+ if (args[i] == '-p') {
+ params[args[++i]] = args[++i];
+ }
+ }
+
+ var invokeThisAction, waitForThisAction;
+
+ var attachedTo = attached[action];
+ if (!attachedTo) {
+ invokeThisAction = action;
+ waitForThisAction = action;
+
+ } else {
+ invokeThisAction = 'owdbg/invoker';
+
+ params.action = action;
+ params.namespace = namespace;
+
+ params.onDone_trigger = attachedTo.triggerName;
+ waitForThisAction = attachedTo.actionName;
+ }
+
+ //console.log("PARAMS", invokeThisAction, params);
+
+ var key = wskprops['AUTH'];
+ var ow = setupOpenWhisk(wskprops);
+ var owForActivations = openwhisk({
+ api: api.host + api.path,
+ api_key: key,
+ namespace: '_'
+ });
+
+ ow.actions.invoke({
+ actionName: invokeThisAction,
+ params: params
+ }).then(function(activation) {
+ if (activation && activation.activationId) {
+ // successfully invoked
+ if (!attachedTo) {
+ console.log('Successfully invoked with activationId', activation.activationId);
+ } else {
+
+ }
+
+ var timer = setInterval(function waitForResponse() {
+ owForActivations.activations.list({ limit: 10 }).then(function(list) {
+ for (var i = 0; i < list.length; i++) {
+ var activation = list[i];
+ if (activation.name == waitForThisAction) {
+ clearInterval(timer);
+ owForActivations.activations.get({ activation: activation.activationId }).then(function(activation) {
+ console.log(JSON.stringify(activation, undefined, 4));
+ next();
+ });
+ break;
+ }
+ }
+ });
+ }, 2000);
+ }
+ });
+}
diff --git a/nodejs/client/package.json b/nodejs/client/package.json
index 9fb35e1..4bf8747 100644
--- a/nodejs/client/package.json
+++ b/nodejs/client/package.json
@@ -10,11 +10,12 @@
"license": "ISC",
"dependencies": {
"colors": "^1.1.2",
+ "columnify": "^1.5.4",
"expand-home-dir": "0.0.3",
+ "inquirer": "^1.1.3",
"node-inspector": "^0.12.8",
"open": "0.0.5",
"openwhisk": "^2.1.3",
- "prompt": "^1.0.0",
"properties-parser": "^0.3.1",
"request": "^2.75.0",
"tmp": "0.0.29",
diff --git a/nodejs/client/wskdb.js b/nodejs/client/wskdb.js
index 7ae6fe2..c99ea27 100644
--- a/nodejs/client/wskdb.js
+++ b/nodejs/client/wskdb.js
@@ -2,10 +2,10 @@
tmp = require('tmp'),
open = require('open'),
path = require('path'),
+ repl = require('./lib/repl').repl,
spawn = require('child_process').spawn,
colors = require('colors'),
- prompt = require('prompt'),
- openwhisk = require('openwhisk'),
+ columnify = require('columnify'),
WebSocket = require('ws'),
expandHomeDir = require('expand-home-dir'),
propertiesParser = require('properties-parser'),
@@ -23,13 +23,23 @@
var ws = new WebSocket(broker.host + broker.path);
ws.on('open', function open() {
- console.log('The wskdb client is ready to debug!');
+ console.log('Welcome to the OpenWhisk Debugger');
+ console.log();
- var key = propertiesParser.read(expandHomeDir('~/.wskprops'))['AUTH'];
+ var wskprops = propertiesParser.read(expandHomeDir('~/.wskprops'));
+ var key = wskprops['AUTH'];
ws.send(JSON.stringify({
type: 'init',
key: key
}));
+
+ var keepAlive = setInterval(function poke() {
+ ws.send(JSON.stringify({
+ type: 'keep-alive'
+ }));
+ }, 5000);
+
+ repl(wskprops);
});
ws.on('close', function() {
@@ -50,17 +60,9 @@
console.log('Debug session requested');
//console.log(JSON.stringify(message, undefined, 4));
- var keepAlive = setInterval(function poke() {
- ws.send(JSON.stringify({
- type: 'keep-alive'
- }));
- }, 5000);
-
function done(err, result) {
console.log('Finishing up this debug session');
- clearInterval(keepAlive);
-
ws.send(JSON.stringify({
type: err ? 'circuit-breaker' : 'end',
key: message.key,
@@ -98,7 +100,6 @@
});
function debugDebug(message, ws, done) {
- prompt.start();
prompt.get({
name: 'result', description: 'Return value',
conform: function(result) {
@@ -198,9 +199,14 @@
*/
process.on('exit', function onExit() {
- ws.send(JSON.stringify({
- type: 'disconnect'
- }, function ack() {
- ws.close();
- }));
+ try {
+ console.log("Goodbye!".red);
+
+ ws.send(JSON.stringify({
+ type: 'disconnect'
+ }, function ack() {
+ ws.close();
+ }));
+ } catch (e) {
+ }
});
diff --git a/nodejs/client/wskinvoke.sh b/nodejs/client/wskinvoke.sh
index 0af255b..eb990f5 100755
--- a/nodejs/client/wskinvoke.sh
+++ b/nodejs/client/wskinvoke.sh
@@ -24,8 +24,6 @@
wsk action create ${ACTION} lib/echo.js >& /dev/null
wsk rule create ${RULE} ${TRIGGER} ${ACTION} >& /dev/null
-wait
-
wsk action invoke owdbg/invoker -p namespace "${NAMESPACE}" -p onDone_trigger ${TRIGGER} -p action $@
echo -n "Your debugging session should now be active."