Skip to content

Commit

Permalink
Merge branch 'main' of github.com:sk593/vscode-dapr into appMetadata-m…
Browse files Browse the repository at this point in the history
  • Loading branch information
sk593 committed Jul 22, 2021
2 parents c9a97dc + 7b3970b commit 9f8575b
Show file tree
Hide file tree
Showing 13 changed files with 98 additions and 17 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ You can also use the extension to directly publish events to running application

![Publish Message](assets/readme/publishMessage.png)

### Stop Dapr applications

The Dapr extension allows you to directly stop locally-running applications without using the command line.

![Stop Application](assets/readme/stopApp.png)

## Telemetry

### Data Collection
Expand Down
Binary file added assets/readme/stopApp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions i18n/jpn/package.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"vscode-dapr.views.appDetails.title": "Application Details",
"vscode-dapr.views.componentDetails.title": "Component Details",
"vscode-dapr.views.details.title": "Details",
"vscode-dapr.applications.stop-app.title": "Stop Application",
"vscode-dapr.help.readDocumentation.title": "Read Documentation",
"vscode-dapr.help.getStarted.title": "Get Started",
"vscode-dapr.help.reportIssue.title": "Report Issue",
Expand Down
20 changes: 17 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"onCommand:vscode-dapr.applications.invoke-post",
"onCommand:vscode-dapr.applications.publish-all-message",
"onCommand:vscode-dapr.applications.publish-message",
"onCommand:vscode-dapr.applications.stop-app",
"onCommand:vscode-dapr.help.getStarted",
"onCommand:vscode-dapr.help.installDapr",
"onCommand:vscode-dapr.help.readDocumentation",
Expand Down Expand Up @@ -84,6 +85,11 @@
"title": "%vscode-dapr.views.componentDetails.title%",
"category": "Dapr"
},
{
"command": "vscode-dapr.applications.stop-app",
"title": "%vscode-dapr.applications.stop-app.title%",
"category": "Dapr"
},
{
"command": "vscode-dapr.help.getStarted",
"title": "%vscode-dapr.help.getStarted.title%",
Expand Down Expand Up @@ -137,15 +143,23 @@
"view/item/context": [
{
"command": "vscode-dapr.applications.invoke-get",
"when": "view == vscode-dapr.views.applications && viewItem == application"
"when": "view == vscode-dapr.views.applications && viewItem == application",
"group": "invoke"
},
{
"command": "vscode-dapr.applications.invoke-post",
"when": "view == vscode-dapr.views.applications && viewItem == application"
"when": "view == vscode-dapr.views.applications && viewItem == application",
"group": "invoke"
},
{
"command": "vscode-dapr.applications.publish-message",
"when": "view == vscode-dapr.views.applications && viewItem == application"
"when": "view == vscode-dapr.views.applications && viewItem == application",
"group": "invoke"
},
{
"command": "vscode-dapr.applications.stop-app",
"when": "view == vscode-dapr.views.applications && viewItem == application",
"group": "stop"
}
],
"view/title": [
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"vscode-dapr.applications.invoke-post.title": "Invoke (POST) Application Method",
"vscode-dapr.applications.publish-message.title": "Publish Message to Application",
"vscode-dapr.applications.publish-all-message.title": "Publish Message to All Applications",
"vscode-dapr.applications.stop-app.title": "Stop Application",

"vscode-dapr.configuration.paths.daprPath.description": "The full path to the dapr binary.",
"vscode-dapr.configuration.paths.daprdPath.description": "The full path to the daprd binary.",
Expand Down
24 changes: 24 additions & 0 deletions src/commands/applications/stopApp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import DaprApplicationNode from "../../views/applications/daprApplicationNode";
import { UserInput } from '../../services/userInput';
import { IActionContext } from 'vscode-azureextensionui';
import { getLocalizationPathForFile } from '../../util/localization';
import * as nls from 'vscode-nls';
import { DaprCliClient } from "../../services/daprCliClient";

const localize = nls.loadMessageBundle(getLocalizationPathForFile(__filename));

export async function stopApp(daprCliClient: DaprCliClient, ui: UserInput, node: DaprApplicationNode | undefined): Promise<void> {
try {
return daprCliClient.stopApp(node?.application);
} catch {
await ui.showWarningMessage(localize('commands.invokeCommon.stopAppError', 'Failed to stop application \'{0}\'', node?.application.appId),
{ modal: true });
}
}

const createStopCommand = (daprCliClient: DaprCliClient, ui: UserInput) => (context: IActionContext, node: DaprApplicationNode | undefined): Promise<void> => stopApp(daprCliClient, ui, node);

export default createStopCommand;
5 changes: 4 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import LocalScaffolder from './scaffolding/scaffolder';
import NodeEnvironmentProvider from './services/environmentProvider';
import createScaffoldDaprComponentsCommand from './commands/scaffoldDaprComponents';
import VsCodeSettingsProvider from './services/settingsProvider';
import createStopCommand from './commands/applications/stopApp';
import LocalDaprCliClient from './services/daprCliClient';
import createInstallDaprCommand from './commands/help/installDapr';
import DetailsTreeDataProvider from './views/details/detailsTreeDataProvider';
Expand Down Expand Up @@ -71,13 +72,15 @@ export function activate(context: vscode.ExtensionContext): Promise<void> {
const templateScaffolder = new HandlebarsTemplateScaffolder(templatesPath);
const detailsTreeDataProvider = new DetailsTreeDataProvider(daprApplicationProvider)

const daprCliClient = new LocalDaprCliClient(() => settingsProvider.daprPath)

telemetryProvider.registerContextCommandWithTelemetry('vscode-dapr.applications.invoke-get', createInvokeGetCommand(daprApplicationProvider, daprClient, ext.outputChannel, ui, context.workspaceState));
telemetryProvider.registerContextCommandWithTelemetry('vscode-dapr.applications.invoke-post', createInvokePostCommand(daprApplicationProvider, daprClient, ext.outputChannel, ui, context.workspaceState));
telemetryProvider.registerCommandWithTelemetry('vscode-dapr.applications.publish-all-message', createPublishAllMessageCommand(daprApplicationProvider, daprClient, ext.outputChannel, ui, context.workspaceState));
telemetryProvider.registerContextCommandWithTelemetry('vscode-dapr.applications.publish-message', createPublishMessageCommand(daprApplicationProvider, daprClient, ext.outputChannel, ui, context.workspaceState));
telemetryProvider.registerContextCommandWithTelemetry('vscode-dapr.views.appDetails', createSetAppDetailsCommand(detailsTreeDataProvider));
telemetryProvider.registerContextCommandWithTelemetry('vscode-dapr.views.componentDetails', createSetComponentDetailsCommand(detailsTreeDataProvider));
telemetryProvider.registerContextCommandWithTelemetry('vscode-dapr.applications.stop-app', createStopCommand(daprCliClient, ui));
telemetryProvider.registerContextCommandWithTelemetry('vscode-dapr.help.readDocumentation', createReadDocumentationCommand(ui));
telemetryProvider.registerContextCommandWithTelemetry('vscode-dapr.help.getStarted', createGetStartedCommand(ui));
telemetryProvider.registerContextCommandWithTelemetry('vscode-dapr.help.installDapr', createInstallDaprCommand(ui));
Expand All @@ -90,7 +93,7 @@ export function activate(context: vscode.ExtensionContext): Promise<void> {
const daprInstallationManager = new LocalDaprInstallationManager(
extensionPackage.engines['dapr-cli'],
extensionPackage.engines['dapr-runtime'],
new LocalDaprCliClient(() => settingsProvider.daprPath),
daprCliClient,
ui);

registerDisposable(vscode.tasks.registerTaskProvider('dapr', new DaprCommandTaskProvider(daprInstallationManager, () => settingsProvider.daprPath, telemetryProvider)));
Expand Down
8 changes: 5 additions & 3 deletions src/services/daprApplicationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface DaprApplication {
pid: number;
grpcPort: number;
appPort: number | undefined;
ppid: number | undefined;
}

export interface DaprApplicationProvider {
Expand Down Expand Up @@ -70,7 +71,7 @@ function getAppPort(cmd: string): number | undefined {
}
}

function toApplication(cmd: string | undefined, pid: number): DaprApplication | undefined {
function toApplication(cmd: string | undefined, pid: number, ppid: number | undefined): DaprApplication | undefined {
if (cmd) {
const appId = getAppId(cmd);

Expand All @@ -80,7 +81,8 @@ function toApplication(cmd: string | undefined, pid: number): DaprApplication |
httpPort: getHttpPort(cmd),
pid,
grpcPort: getGrpcPort(cmd),
appPort: getAppPort(cmd)
appPort: getAppPort(cmd),
ppid
};
}
}
Expand Down Expand Up @@ -135,7 +137,7 @@ export default class ProcessBasedDaprApplicationProvider extends vscode.Disposab
const processes = await this.processProvider.listProcesses('daprd', this.settingsProvider.daprdPath);

this.applications = processes
.map(process => toApplication(process.cmd, process.pid))
.map(process => toApplication(process.cmd, process.pid, process.ppid))
.filter((application): application is DaprApplication => application !== undefined);

this.onDidChangeEmitter.fire();
Expand Down
16 changes: 16 additions & 0 deletions src/services/daprCliClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import CommandLineBuilder from "../util/commandLineBuilder";
import { Process } from "../util/process";
import * as nls from 'vscode-nls';
import { getLocalizationPathForFile } from '../util/localization';
import { DaprApplication } from "./daprApplicationProvider";
import * as os from 'os'

const localize = nls.loadMessageBundle(getLocalizationPathForFile(__filename));

Expand All @@ -15,6 +17,7 @@ export interface DaprVersion {

export interface DaprCliClient {
version(): Promise<DaprVersion>;
stopApp(application: DaprApplication | undefined): void;
}

export default class LocalDaprCliClient implements DaprCliClient {
Expand Down Expand Up @@ -44,4 +47,17 @@ export default class LocalDaprCliClient implements DaprCliClient {
runtime: runtimeMatch ? runtimeMatch.groups!['version'] : undefined
}
}

stopApp(application: DaprApplication | undefined): void {
const processId = application?.ppid !== undefined ? application.ppid : application?.pid;
if (os.platform() === 'win32') {
// NOTE: Windows does not support SIGTERM/SIGINT/SIGBREAK, so there can be no graceful process shutdown.
// As a partial mitigation, use `taskkill` to kill the entire process tree.
processId !== undefined ? void Process.exec(`taskkill /pid ${processId} /t /f`) : null;
} else {
processId !== undefined ? process.kill(processId, 'SIGTERM') : null;
}
}


}
8 changes: 5 additions & 3 deletions src/services/daprClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DaprApplication } from "./daprApplicationProvider";
import { HttpClient, HttpResponse } from './httpClient';
import { getLocalizationPathForFile } from '../util/localization';


const localize = nls.loadMessageBundle(getLocalizationPathForFile(__filename));

export interface DaprClient {
Expand Down Expand Up @@ -61,7 +62,7 @@ export default class HttpDaprClient implements DaprClient {

await this.httpClient.post(url, payload, { json: true }, token);
}

async getMetadata(application: DaprApplication, token?: vscode.CancellationToken | undefined): Promise<DaprMetadata> {
const originalUrl = `http://localhost:${application.httpPort}/v1.0/metadata`;

Expand All @@ -70,7 +71,7 @@ export default class HttpDaprClient implements DaprClient {
return manageResponse(response) as DaprMetadata;
}
}

export interface DaprMetadata {
components: DaprComponentMetadata[];
}
Expand All @@ -79,4 +80,5 @@ export interface DaprMetadata {
name: string;
type: string;
version: string;
}
}

2 changes: 1 addition & 1 deletion src/services/daprInstallationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,4 @@ export default class LocalDaprInstallationManager implements DaprInstallationMan
context.suppressReportIssue = true;
}
}
}
}
23 changes: 17 additions & 6 deletions src/services/processProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,20 @@ export interface ProcessInfo {
cmd: string;
name: string;
pid: number;
ppid: number | undefined;
}

export interface ProcessProvider {
listProcesses(name: string, daprdPath: string): Promise<ProcessInfo[]>;
}

export class UnixProcessProvider implements ProcessProvider {

async listProcesses(name: string, daprdPath: string): Promise<ProcessInfo[]> {
const processes = await psList();
return processes
const temp = processes
.filter(process => process.name === name || this.hasDaprdPath(process, daprdPath))
.map(process => ({ name: process.name, cmd: process.cmd ?? '', pid: process.pid }));
.map(process => ({ name: process.name, cmd: process.cmd ?? '', pid: process.pid , ppid: this.getDaprPpid(process, daprdPath)}));
return temp;
}

hasDaprdPath(process: psList.ProcessDescriptor, daprdPath: string): boolean | undefined {
Expand All @@ -44,6 +45,14 @@ export class UnixProcessProvider implements ProcessProvider {
}
}
}

getDaprPpid(process: psList.ProcessDescriptor, daprdPath: string): number | undefined {
if(this.hasDaprdPath(process, daprdPath)) {
return process.ppid
}
return undefined;
}

}


Expand All @@ -55,7 +64,7 @@ function getWmicValue(line: string): string {

export class WindowsProcessProvider implements ProcessProvider {
async listProcesses(name: string): Promise<ProcessInfo[]> {
const list = await Process.exec(`wmic process where "name='${name}.exe'" get commandline,name,processid /format:list`);
const list = await Process.exec(`wmic process where "name='${name}.exe'" get commandline,name,parentprocessid,processid /format:list`);

// Lines in the output are delimited by "<CR><CR><LF>".
const lines = list.stdout.split('\r\r\n');
Expand All @@ -71,9 +80,11 @@ export class WindowsProcessProvider implements ProcessProvider {

const cmd = getWmicValue(lines[(i * 5) + 2]);
const name = getWmicValue(lines[(i * 5) + 3]);
const pid = parseInt(getWmicValue(lines[(i * 5) + 4]), 10);
const ppid = parseInt(getWmicValue(lines[(i*5) + 4]), 10);
const pid = parseInt(getWmicValue(lines[(i * 5) + 5]), 10);


processes.push({ cmd, name, pid });
processes.push({ cmd, name, pid, ppid});
}

return processes;
Expand Down
1 change: 1 addition & 0 deletions src/views/applications/daprApplicationTreeDataProvider.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

Expand Down

0 comments on commit 9f8575b

Please sign in to comment.