Skip to content

Commit

Permalink
Change verify config action to pass --ide, changing some target relat…
Browse files Browse the repository at this point in the history
…ed errors to warnings. (#71)

* Change verify config action to pass --ide, changing some target related errors to warnings.

* wrap entry in try/catch

* log stdout

* move entrypoint to a function so we dont have a huge try/catch

* changelog

* formatting

* log catch

* revert --path

* lint
  • Loading branch information
meowjesty authored Oct 6, 2023
1 parent 463b2e3 commit 483d1db
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 220 deletions.
1 change: 1 addition & 0 deletions changelog.d/72.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Uses the `verify-config --ide` flag now to signal mirrord we're in an IDE context. Changes `isTargetSet` to check for both `null` and `undefined`.
10 changes: 6 additions & 4 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ export class MirrordAPI {
child.stdout.on("data", (data) => stdoutData += data.toString());
child.stderr.on("data", (data) => stderrData += data.toString());

child.stdout.on('end', () => console.log(`${stdoutData}`));
child.stderr.on('end', () => console.log(`${stderrData}`));

child.on("error", (err) => {
console.error(err);
reject(`process failed: ${err.message}`);
Expand Down Expand Up @@ -197,7 +200,7 @@ export class MirrordAPI {
});
}

/**
/**
* Spawn the mirrord cli with the given arguments.
* Used for reading/interacting while process still runs.
*/
Expand Down Expand Up @@ -248,9 +251,8 @@ export class MirrordAPI {
* `VerifiedConfig`.
*/
async verifyConfig(configPath: vscode.Uri | null): Promise<VerifiedConfig | undefined> {
const args = ['verify-config'];
if (configPath) {
args.push(configPath.path);
const args = ['verify-config', '--ide', `${configPath.path}`];
const stdout = await this.exec(args);

const verifiedConfig: VerifiedConfig = JSON.parse(stdout);
Expand Down Expand Up @@ -396,7 +398,7 @@ class MirrordWarningHandler {
}
}

/**
/**
* Updates the global feedback counter.
* After each `FEEDBACK_COUNTER_REVIEW_AFTER` mirrord runs, displays a message asking the user to leave a review in the marketplace.
*/
Expand Down
5 changes: 1 addition & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import * as vscode from 'vscode';
import YAML from 'yaml';
import TOML from 'toml';
import { NotificationBuilder } from './notification';
import { mirrordFailure } from './api';

/**
* Default mirrord configuration.
Expand Down Expand Up @@ -69,7 +66,7 @@ export function isTargetSet(verifiedConfig: VerifiedConfig): boolean {
switch (verifiedConfig.type) {
case 'Success':
verifiedConfig.warnings.forEach((warn) => new NotificationBuilder().withMessage(warn).warning());
return verifiedConfig.config.path !== undefined;
return verifiedConfig.config.path !== undefined && verifiedConfig.config.path !== null;
case 'Fail':
verifiedConfig.errors.forEach((fail) => new NotificationBuilder().withMessage(fail).error());
throw new Error('mirrord verify-config detected an invalid configuration!');
Expand Down
216 changes: 116 additions & 100 deletions src/debugger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,137 +85,153 @@ function setLastActiveMirrordPath(path: string) {
}

/**
* We implement the `resolveDebugConfiguration` that comes with vscode variables resolved already.
* Entrypoint for the vscode extension, called from `resolveDebugConfigurationWithSubstitutedVariables`.
*/
export class ConfigurationProvider implements vscode.DebugConfigurationProvider {
async resolveDebugConfigurationWithSubstitutedVariables(
folder: vscode.WorkspaceFolder | undefined,
config: vscode.DebugConfiguration,
token: vscode.CancellationToken): Promise<vscode.DebugConfiguration | null | undefined> {

if (!globalContext.workspaceState.get('enabled')) {
return config;
}
async function main(
folder: vscode.WorkspaceFolder | undefined,
config: vscode.DebugConfiguration,
_token: vscode.CancellationToken): Promise<vscode.DebugConfiguration | null | undefined> {
if (!globalContext.workspaceState.get('enabled')) {
return config;
}

// For some reason resolveDebugConfiguration runs twice for Node projects. __parentId is populated.
if (config.__parentId || config.env?.["__MIRRORD_EXT_INJECTED"] === 'true') {
return config;
}
// For some reason resolveDebugConfiguration runs twice for Node projects. __parentId is populated.
if (config.__parentId || config.env?.["__MIRRORD_EXT_INJECTED"] === 'true') {
return config;
}

updateTelemetries();
updateTelemetries();

//TODO: add progress bar maybe ?
let cliPath;
//TODO: add progress bar maybe ?
let cliPath;

try {
cliPath = await getMirrordBinary();
} catch (err) {
// Get last active, that should work?
cliPath = await getLastActiveMirrordPath();

// Well try any mirrord we can try :\
try {
cliPath = await getMirrordBinary();
} catch (err) {
// Get last active, that should work?
cliPath = await getLastActiveMirrordPath();

// Well try any mirrord we can try :\
if (!cliPath) {
cliPath = await getLocalMirrordBinary();
if (!cliPath) {
cliPath = await getLocalMirrordBinary();
if (!cliPath) {
mirrordFailure(`Couldn't download mirrord binaries or find local one in path ${err}.`);
return null;
}
mirrordFailure(`Couldn't download mirrord binaries or find local one in path ${err}.`);
return null;
}
}
setLastActiveMirrordPath(cliPath);
}
setLastActiveMirrordPath(cliPath);

let mirrordApi = new MirrordAPI(cliPath);
let mirrordApi = new MirrordAPI(cliPath);

config.env ||= {};
let target = null;
config.env ||= {};
let target = null;

let configPath = await MirrordConfigManager.getInstance().resolveMirrordConfig(folder, config);
const verifiedConfig = await mirrordApi.verifyConfig(configPath);
let configPath = await MirrordConfigManager.getInstance().resolveMirrordConfig(folder, config);
const verifiedConfig = await mirrordApi.verifyConfig(configPath);

// If target wasn't specified in the config file (or there's no config file), let user choose pod from dropdown
if (!configPath || (verifiedConfig && !isTargetSet(verifiedConfig))) {
let targets;
try {
targets = await mirrordApi.listTargets(configPath?.path);
} catch (err) {
mirrordFailure(`mirrord failed to list targets: ${err}`);
return null;
}
if (targets.length === 0) {
new NotificationBuilder()
.withMessage(
"No mirrord target available in the configured namespace. " +
"You can run targetless, or set a different target namespace or kubeconfig in the mirrord configuration file.",
)
.info();
}

let selected = false;
// If target wasn't specified in the config file (or there's no config file), let user choose pod from dropdown
if (!configPath || (verifiedConfig && !isTargetSet(verifiedConfig))) {
let targets;
try {
targets = await mirrordApi.listTargets(configPath?.path);
} catch (err) {
mirrordFailure(`mirrord failed to list targets: ${err}`);
return null;
}
if (targets.length === 0) {
new NotificationBuilder()
.withMessage(
"No mirrord target available in the configured namespace. " +
"You can run targetless, or set a different target namespace or kubeconfig in the mirrord configuration file.",
)
.info();
}

while (!selected) {
let targetPick = await vscode.window.showQuickPick(targets.quickPickItems(), {
placeHolder: 'Select a target path to mirror'
});
let selected = false;

if (targetPick) {
if (targetPick.type === 'page') {
targets.switchPage(targetPick);
while (!selected) {
let targetPick = await vscode.window.showQuickPick(targets.quickPickItems(), {
placeHolder: 'Select a target path to mirror'
});

continue;
}
if (targetPick) {
if (targetPick.type === 'page') {
targets.switchPage(targetPick);

if (targetPick.type !== 'targetless') {
target = targetPick.value;
}
continue;
}

globalContext.globalState.update(LAST_TARGET_KEY, target);
globalContext.workspaceState.update(LAST_TARGET_KEY, target);
if (targetPick.type !== 'targetless') {
target = targetPick.value;
}

selected = true;
globalContext.globalState.update(LAST_TARGET_KEY, target);
globalContext.workspaceState.update(LAST_TARGET_KEY, target);
}

if (!target) {
new NotificationBuilder()
.withMessage("mirrord running targetless")
.withDisableAction("promptTargetless")
.info();
}
selected = true;
}

if (config.type === "go") {
config.env["MIRRORD_SKIP_PROCESSES"] = "dlv;debugserver;compile;go;asm;cgo;link;git;gcc;as;ld;collect2;cc1";
} else if (config.type === "python") {
config.env["MIRRORD_DETECT_DEBUGGER_PORT"] = "debugpy";
} else if (config.type === "java") {
config.env["MIRRORD_DETECT_DEBUGGER_PORT"] = "javaagent";
if (!target) {
new NotificationBuilder()
.withMessage("mirrord running targetless")
.withDisableAction("promptTargetless")
.info();
}
}

// Add a fixed range of ports that VS Code uses for debugging.
// TODO: find a way to use MIRRORD_DETECT_DEBUGGER_PORT for other debuggers.
config.env["MIRRORD_IGNORE_DEBUGGER_PORTS"] = "45000-65535";
if (config.type === "go") {
config.env["MIRRORD_SKIP_PROCESSES"] = "dlv;debugserver;compile;go;asm;cgo;link;git;gcc;as;ld;collect2;cc1";
} else if (config.type === "python") {
config.env["MIRRORD_DETECT_DEBUGGER_PORT"] = "debugpy";
} else if (config.type === "java") {
config.env["MIRRORD_DETECT_DEBUGGER_PORT"] = "javaagent";
}

let isMac = platform() === "darwin";
// Add a fixed range of ports that VS Code uses for debugging.
// TODO: find a way to use MIRRORD_DETECT_DEBUGGER_PORT for other debuggers.
config.env["MIRRORD_IGNORE_DEBUGGER_PORTS"] = "45000-65535";

let [executableFieldName, executable] = isMac ? getFieldAndExecutable(config) : [null, null];
let isMac = platform() === "darwin";

let executionInfo;
try {
executionInfo = await mirrordApi.binaryExecute(target, configPath?.path || null, executable);
} catch (err) {
mirrordFailure(`mirrord preparation failed: ${err}`);
return null;
}
let [executableFieldName, executable] = isMac ? getFieldAndExecutable(config) : [null, null];

if (isMac) {
changeConfigForSip(config, executableFieldName as string, executionInfo);
}
let executionInfo;
try {
executionInfo = await mirrordApi.binaryExecute(target, configPath?.path || null, executable);
} catch (err) {
mirrordFailure(`mirrord preparation failed: ${err}`);
return null;
}

let env = executionInfo?.env;
config.env = Object.assign({}, config.env, Object.fromEntries(env));
if (isMac) {
changeConfigForSip(config, executableFieldName as string, executionInfo);
}

config.env["__MIRRORD_EXT_INJECTED"] = 'true';
let env = executionInfo?.env;
config.env = Object.assign({}, config.env, Object.fromEntries(env));

return config;
config.env["__MIRRORD_EXT_INJECTED"] = 'true';

return config;
}

/**
* We implement the `resolveDebugConfiguration` that comes with vscode variables resolved already.
*/
export class ConfigurationProvider implements vscode.DebugConfigurationProvider {
async resolveDebugConfigurationWithSubstitutedVariables(
folder: vscode.WorkspaceFolder | undefined,
config: vscode.DebugConfiguration,
_token: vscode.CancellationToken): Promise<vscode.DebugConfiguration | null | undefined> {
try {
return await main(folder, config, _token);
} catch (fail) {
console.error(`Something went wrong in the extension: ${fail}`);
new NotificationBuilder()
.withMessage(`Something went wrong: ${fail}`)
.error();
}
}
}
Loading

0 comments on commit 483d1db

Please sign in to comment.