Skip to content

Commit

Permalink
feat: allow user to open visualization in browser
Browse files Browse the repository at this point in the history
  • Loading branch information
theburningmonk committed Oct 10, 2019
1 parent d994d38 commit 4bc2016
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 9 deletions.
29 changes: 29 additions & 0 deletions src/commands/powertune-lambda.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
const _ = require("lodash");
const AWS = require("aws-sdk");
const Semver = require("semver");
const Retry = require("async-retry");
const uuid = require("uuid/v4");
const {Command, flags} = require("@oclif/command");
const {checkVersion} = require("../lib/version-check");
const fs = require("fs");
const inquirer = require("inquirer");
const childProcess = require("child_process");
require("colors");

const ApplicationId = "arn:aws:serverlessrepo:us-east-1:451282441545:applications/aws-lambda-power-tuning";
Expand Down Expand Up @@ -63,6 +66,23 @@ class PowertuneLambdaCommand extends Command {

const result = await waitForStateMachineOutput(executionArn);
this.log(JSON.stringify(result, null, 2).yellow);

// since v2.1.1 the powertuning SFN returns a visualization URL as well
const visualizationUrl = _.get(result, "results.stateMachine.visualization");
if (visualizationUrl) {
const {visualize} = await inquirer.prompt([
{
type: "list",
name: "visualize",
message: "Do you want to open the visualization to see more results?",
choices: ["yes", "no"]
}
]);

if (visualize === "yes") {
openVisualization(visualizationUrl);
}
}
}
}

Expand Down Expand Up @@ -109,6 +129,15 @@ PowertuneLambdaCommand.flags = {
})
};

const openVisualization = (url) => {
try {
// this works on many platforms
childProcess.execSync(`python -m webbrowser "${url}"`);
} catch (err) {
childProcess.execSync(`open "${url}"`);
}
};

const getLatestVersion = async (nextToken, acc) => {
const ServerlessRepo = new AWS.ServerlessApplicationRepository();
const resp = await ServerlessRepo.listApplicationVersions({
Expand Down
20 changes: 12 additions & 8 deletions src/lib/version-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ const semver = require("semver");
const checkVersion = () => {
const packageJson = require("../../package.json");
const version = packageJson.version;
const npmVersion = childProcess.execSync("npm show lumigo-cli version").toString().trim();
try {
const npmVersion = childProcess.execSync("npm show lumigo-cli version").toString().trim();

if (semver.gt(npmVersion, version)) {
console.log(`
===============================================================
v${npmVersion} of this CLI is now available on NPM.
Please run "npm i -g lumigo-cli" to update :-)
===============================================================
`);
if (semver.gt(npmVersion, version)) {
console.log(`
===============================================================
v${npmVersion} of this CLI is now available on NPM.
Please run "npm i -g lumigo-cli" to update :-)
===============================================================
`);
}
// eslint-disable-next-line no-empty
} catch (err) {
}
};

Expand Down
70 changes: 69 additions & 1 deletion test/commands/powertune-lambda.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const _ = require("lodash");
const {expect, test} = require("@oclif/test");
const AWS = require("aws-sdk");
const fs = require("fs");
const inquirer = require("inquirer");
const childProcess = require("child_process");

const mockListApplicationVersions = jest.fn();
AWS.ServerlessApplicationRepository.prototype.listApplicationVersions = mockListApplicationVersions;
Expand All @@ -19,6 +22,10 @@ AWS.StepFunctions.prototype.startExecution = mockStartExecution;
const mockDescribeExecution = jest.fn();
AWS.StepFunctions.prototype.describeExecution = mockDescribeExecution;
const mockReadFileSync = jest.fn();
const mockPrompt = jest.fn();
inquirer.prompt = mockPrompt;
const mockExecSync = jest.fn();
childProcess.execSync = mockExecSync;

const consoleLog = jest.fn();
console.log = consoleLog;
Expand Down Expand Up @@ -51,6 +58,8 @@ beforeEach(() => {
});

mockReadFileSync.mockReturnValueOnce(fileContent);
mockPrompt.mockImplementation(() => ({ visualize: "no" }));
mockExecSync.mockImplementation(() => "");
});

afterEach(() => {
Expand All @@ -59,11 +68,13 @@ afterEach(() => {
mockGetCloudFormationTemplate.mockReset();
mockDescribeStacks.mockReset();
mockCreateStack.mockReset();
// mockUpdateStack.mockReset();
mockUpdateStack.mockReset();
mockStartExecution.mockReset();
mockDescribeExecution.mockReset();
consoleLog.mockReset();
mockReadFileSync.mockReset();
mockPrompt.mockReset();
mockExecSync.mockReset();
});

const stateMachineArn = "arn:aws:states:us-east-1:123:execution:powerTuningStateMachine";
Expand Down Expand Up @@ -261,6 +272,59 @@ describe("powertune-lambda", () => {
expect(input.payload).to.equal(fileContent);
});
});

describe("when user chooses to visualize the result", () => {
beforeEach(() => {
givenListAppVersionsReturns(["0.0.1", "0.1.0", "1.0.0"]);
givenDescribeStacksReturns("CREATE_COMPLETE", "1.0.0", stateMachineArn);
givenDescribeExecutionReturns("SUCCEEDED", {
results: {
stateMachine: {
visualization: "https://lambda-power-tuning.show/#123"
}
}
});
givenUserChooseToVisualizeResult();
});

test
.stdout()
.command(["powertune-lambda", "-n", "my-function", "-s", "speed", "-r", "us-east-1"])
.it("opens the browser with Python", () => {
const commands = _.flatMap(mockExecSync.mock.calls).join("\n");
expect(commands).to.contain(['python -m webbrowser "https://lambda-power-tuning.show/#123"']);
});

describe("if python is not available", () => {
beforeEach(() => {
givenListAppVersionsReturns(["0.0.1", "0.1.0", "1.0.0"]);
givenDescribeStacksReturns("CREATE_COMPLETE", "1.0.0", stateMachineArn);
givenDescribeExecutionReturns("SUCCEEDED", {
results: {
stateMachine: {
visualization: "https://lambda-power-tuning.show/#123"
}
}
});
givenUserChooseToVisualizeResult();
mockExecSync.mockImplementation(cmd => {
if (cmd.startsWith("python")) {
throw new Error("python: command not found");
} else {
return "";
}
});
});

test
.stdout()
.command(["powertune-lambda", "-n", "my-function", "-s", "speed", "-r", "us-east-1"])
.it("opens the browser with native 'open' command", () => {
const commands = _.flatMap(mockExecSync.mock.calls).join("\n");
expect(commands).to.contain(['open "https://lambda-power-tuning.show/#123"']);
});
});
});
});

function givenListAppVersionsReturns(versions, hasMore = false) {
Expand Down Expand Up @@ -327,3 +391,7 @@ function givenDescribeExecutionReturns(status, output) {
})
});
}

function givenUserChooseToVisualizeResult() {
mockPrompt.mockImplementation(() => ({ visualize: "yes" }));
}

0 comments on commit 4bc2016

Please sign in to comment.