This is an automated email from the ASF dual-hosted git repository. alexkli pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openwhisk-wskdebug.git
commit 4dc9faaac0b1de751d3a81f425f1559c539e95a0 Author: Alexander Klimetschek <aklim...@adobe.com> AuthorDate: Fri Apr 10 18:17:50 2020 -0700 fix: if agent was leftover restore first before installing agent --- package-lock.json | 2 +- src/agentmgr.js | 75 ++++++++++++++++++++++++++++------------------ src/debugger.js | 21 ++++--------- test/agentmgr.test.js | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/test.js | 1 + 5 files changed, 136 insertions(+), 46 deletions(-) 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 @@ class AgentMgr { } } - 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 @@ class AgentMgr { 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 @@ class AgentMgr { // 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 @@ class AgentMgr { // need to look at the original action action = backup; - agentAlreadyInstalled = true; this.agentInstalled = true; } @@ -139,7 +139,21 @@ class AgentMgr { } } } - 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 @@ class AgentMgr { async shutdown() { try { - await this.restoreAction(); + if (this.agentInstalled) { + await this.restoreAction(); + } } finally { if (this.ngrokAgent) { await this.ngrokAgent.stop(); @@ -378,33 +394,34 @@ class AgentMgr { // --------------------------------------< 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 @@ class Debugger { 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 @@ class Debugger { 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 @@ describe('agentmgr', function() { 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 mockAgentPoll(name) { function expectAgentInvocation(name, params, result) { params = params || {}; const activationId = Date.now(); + result = result || {}; result.$activationId = activationId; // wskdebug agent ping for new activation