fix: if agent was leftover restore first before installing agent
diff --git a/package-lock.json b/package-lock.json
index 80aff0c..28b394f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@openwhisk/wskdebug",
- "version": "1.2.0",
+ "version": "1.3.0-RC",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/src/agentmgr.js b/src/agentmgr.js
index c83f31c..ecf33a2 100644
--- a/src/agentmgr.js
+++ b/src/agentmgr.js
@@ -92,7 +92,10 @@
}
}
- async readAction() {
+ /**
+ * Fast way to get just the action metadata
+ */
+ async peekAction() {
if (this.argv.verbose) {
console.log(`Getting action metadata from OpenWhisk: ${this.actionName}`);
}
@@ -101,9 +104,7 @@
throw new Error(`Action not found: ${this.actionName}`);
}
- let agentAlreadyInstalled = false;
-
- // check if this actoin needs to
+ // check if there was an agent leftover
if (isAgent(action)) {
// ups, action is our agent, not the original
// happens if a previous wskdebug was killed and could not restore before it exited
@@ -111,7 +112,7 @@
// check the backup action
try {
- const backup = await this.wsk.actions.get(backupName);
+ const backup = await getWskActionWithoutCode(this.wsk, backupName);
if (isAgent(backup)) {
// backup is also an agent (should not happen)
@@ -124,7 +125,6 @@
// need to look at the original action
action = backup;
- agentAlreadyInstalled = true;
this.agentInstalled = true;
}
@@ -139,7 +139,21 @@
}
}
}
- return {action, agentAlreadyInstalled };
+ return action;
+ }
+
+ async readActionWithCode() {
+ if (this.argv.verbose) {
+ console.log(`Fetching action code from OpenWhisk: ${this.actionName}`);
+ }
+
+ // user can switch between agents (ngrok or not), hence we need to restore first
+ // (better would be to track the agent + its version and avoid a restore, but that's TBD)
+ if (this.agentInstalled) {
+ return this.restoreAction();
+ }
+
+ return this.wsk.actions.get(this.actionName);
}
async installAgent(action, invoker) {
@@ -218,7 +232,9 @@
async shutdown() {
try {
- await this.restoreAction();
+ if (this.agentInstalled) {
+ await this.restoreAction();
+ }
} finally {
if (this.ngrokAgent) {
await this.ngrokAgent.stop();
@@ -378,33 +394,34 @@
// --------------------------------------< restoring >------------------
async restoreAction() {
- if (this.agentInstalled) {
- if (this.argv.verbose) {
- console.log();
- console.log(`Restoring action`);
- }
+ if (this.argv.verbose) {
+ console.log();
+ console.log(`Restoring action`);
+ }
- const copy = getActionCopyName(this.actionName);
+ const copy = getActionCopyName(this.actionName);
- try {
- const original = await this.wsk.actions.get(copy);
+ try {
+ // the original was backed up in the copy
+ const original = await this.wsk.actions.get(copy);
- // copy the backup (copy) to the regular action
- await this.wsk.actions.update({
- name: this.actionName,
- action: original
- });
+ // copy the backup (copy) to the regular action
+ await this.wsk.actions.update({
+ name: this.actionName,
+ action: original
+ });
- // remove the backup
- await this.wsk.actions.delete(copy);
+ // remove the backup
+ await this.wsk.actions.delete(copy);
- // remove any helpers if they exist
- await deleteActionIfExists(this.wsk, `${this.actionName}_wskdebug_invoked`);
- await deleteActionIfExists(this.wsk, `${this.actionName}_wskdebug_completed`);
+ // remove any helpers if they exist
+ await deleteActionIfExists(this.wsk, `${this.actionName}_wskdebug_invoked`);
+ await deleteActionIfExists(this.wsk, `${this.actionName}_wskdebug_completed`);
- } catch (e) {
- console.error("Error while restoring original action:", e);
- }
+ return original;
+
+ } catch (e) {
+ console.error("Error while restoring original action:", e);
}
}
diff --git a/src/debugger.js b/src/debugger.js
index cd8a913..3bf6433 100644
--- a/src/debugger.js
+++ b/src/debugger.js
@@ -54,11 +54,11 @@
console.info(`Starting debugger for /${this.wskProps.namespace}/${this.actionName}`);
- // get the action
- const { action, agentAlreadyInstalled } = await this.agentMgr.readAction();
+ // get the action metadata
+ const actionMetadata = await this.agentMgr.peekAction();
// local debug container
- this.invoker = new OpenWhiskInvoker(this.actionName, action, this.argv, this.wskProps, this.wsk);
+ this.invoker = new OpenWhiskInvoker(this.actionName, actionMetadata, this.argv, this.wskProps, this.wsk);
try {
// run build initially (would be required by starting container)
@@ -71,22 +71,11 @@
await this.invoker.startContainer();
// get code and /init local container
- if (this.argv.verbose) {
- console.log(`Fetching action code from OpenWhisk: ${this.actionName}`);
- }
- const actionWithCode = await this.wsk.actions.get(this.actionName);
- action.exec = actionWithCode.exec;
+ const actionWithCode = await this.agentMgr.readActionWithCode();
await this.invoker.init(actionWithCode);
// setup agent in openwhisk
-
- // user can switch between agents (ngrok or not), hence we need to restore
- // (better would be to track the agent + its version and avoid a restore, but that's TBD)
- if (agentAlreadyInstalled) {
- await this.agentMgr.restoreAction();
- }
-
- await this.agentMgr.installAgent(action, this.invoker);
+ await this.agentMgr.installAgent(actionWithCode, this.invoker);
if (this.argv.onStart) {
console.log("On start:", this.argv.onStart);
diff --git a/test/agentmgr.test.js b/test/agentmgr.test.js
index cf069b7..d9163c9 100644
--- a/test/agentmgr.test.js
+++ b/test/agentmgr.test.js
@@ -19,6 +19,7 @@
'use strict';
+const wskdebug = require('../index');
const Debugger = require("../src/debugger");
const test = require('./test');
@@ -161,4 +162,86 @@
test.assertAllNocksInvoked();
});
+
+ it("should handle if the agent was left around from a previous run", async function() {
+ const action = "myaction";
+ const actionCode = `const main = () => ({ msg: 'CORRECT' });`;
+ const agentCode = `const main = () => ({ msg: 'WRONG' });`;
+
+ // 1. action - both w/o and with code, but holds the agent
+ const agentDescriptionWithoutCode = test.nodejsActionDescription(action);
+ agentDescriptionWithoutCode.annotations.push({ "key": "wskdebug", "value": true });
+
+ const agentDescription = test.nodejsActionDescription(action);
+ agentDescription.annotations.push({ "key": "wskdebug", "value": true });
+ agentDescription.exec.code = agentCode;
+
+ test.openwhiskNock()
+ .get(`${test.openwhiskApiUrlActions()}/${action}`)
+ .matchHeader("authorization", test.openwhiskApiAuthHeader())
+ .query({"code":"false"})
+ .reply(200, agentDescriptionWithoutCode);
+
+ test.openwhiskNock()
+ .get(`${test.openwhiskApiUrlActions()}/${action}`)
+ .matchHeader("authorization", test.openwhiskApiAuthHeader())
+ .optionally()
+ .reply(200, agentDescription);
+
+ // 2. backup of action
+ const actionDescriptionWithoutCode = test.nodejsActionDescription(`${action}_wskdebug_original`);
+ const actionDescription = test.nodejsActionDescription(`${action}_wskdebug_original`);
+ actionDescription.exec.code = actionCode;
+
+ test.openwhiskNock()
+ .get(`${test.openwhiskApiUrlActions()}/${action}_wskdebug_original`)
+ .matchHeader("authorization", test.openwhiskApiAuthHeader())
+ .query({"code":"false"})
+ .reply(200, actionDescriptionWithoutCode);
+
+ test.openwhiskNock()
+ .get(`${test.openwhiskApiUrlActions()}/${action}_wskdebug_original`)
+ .matchHeader("authorization", test.openwhiskApiAuthHeader())
+ .reply(200, actionDescription);
+
+ // 3. restoring (before start)
+ test.openwhiskNock()
+ .put(
+ `${test.openwhiskApiUrlActions()}/${action}?overwrite=true`,
+ body => body.exec && body.exec.code === actionCode
+ )
+ .matchHeader("authorization", test.openwhiskApiAuthHeader())
+ .reply(200, agentDescriptionWithoutCode);
+
+ test.mockRemoveBackupAction(action);
+
+ // 4. install agent
+ test.openwhiskNock()
+ .put(
+ `${test.openwhiskApiUrlActions()}/${action}?overwrite=true`,
+ body => body.annotations.some(v => v.key === "wskdebug" && v.value === true)
+ )
+ .matchHeader("authorization", test.openwhiskApiAuthHeader())
+ .reply(200, agentDescription);
+
+ test.mockCreateBackupAction(action);
+
+ // 5. invocation
+ test.expectAgentInvocation(
+ action,
+ {},
+ { msg: "CORRECT" }
+ );
+
+ // 6. restore
+ test.mockReadBackupAction(action, actionCode);
+ test.mockRestoreAction(action, actionCode);
+ test.mockRemoveBackupAction(action);
+
+ // -----------------
+
+ await wskdebug(`${action}`);
+
+ test.assertAllNocksInvoked();
+ });
});
diff --git a/test/test.js b/test/test.js
index c01f8c2..d39c539 100644
--- a/test/test.js
+++ b/test/test.js
@@ -213,6 +213,7 @@
function expectAgentInvocation(name, params, result) {
params = params || {};
const activationId = Date.now();
+ result = result || {};
result.$activationId = activationId;
// wskdebug agent ping for new activation