Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass config env vars to mirrord verify-config. #74

Merged
merged 15 commits into from
Oct 19, 2023
Merged
1 change: 1 addition & 0 deletions changelog.d/70.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Passes the `launch.json` `env` section to `mirrord verify-config`, resolving config options that were set as env vars.
72 changes: 46 additions & 26 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { globalContext } from './extension';
import { tickWaitlistCounter } from './waitlist';
import { NotificationBuilder } from './notification';
import { MirrordStatus } from './status';
import { VerifiedConfig } from './config';
import { EnvVars, VerifiedConfig } from './config';
import { PathLike } from 'fs';

/**
* Key to access the feedback counter (see `tickFeedbackCounter`) from the global user config.
Expand Down Expand Up @@ -133,6 +134,30 @@ export class MirrordExecution {

}

/**
* Sets up the args that are going to be passed to the mirrord cli.
*/
const makeMirrordArgs = (target: string | null, configFilePath: PathLike | null, userExecutable: PathLike | null): readonly string[] => {
let args = ["ext"];

if (target) {
console.log(`target ${target}`);
args.push("-t", target);
}

if (configFilePath) {
console.log(`configFilePath ${configFilePath.toString()}`);
args.push("-f", configFilePath.toString());
}

if (userExecutable) {
console.log(`userExecutable ${userExecutable.toString()}`);
args.push("-e", userExecutable.toString());
}

return args;
};

/**
* API to interact with the mirrord CLI, runs in the "ext" mode.
*/
Expand All @@ -144,18 +169,19 @@ export class MirrordAPI {
}

// Return environment for the spawned mirrord cli processes.
private static getEnv(): NodeJS.ProcessEnv {
private static getEnv(configEnv: EnvVars): NodeJS.ProcessEnv {
// clone env vars and add MIRRORD_PROGRESS_MODE
return {
...process.env,
...configEnv,
// eslint-disable-next-line @typescript-eslint/naming-convention
"MIRRORD_PROGRESS_MODE": "json",
...process.env,
};
}

// Execute the mirrord cli with the given arguments, return stdout.
private async exec(args: string[]): Promise<string> {
const child = this.spawn(args);
private async exec(args: string[], configEnv: EnvVars): Promise<string> {
const child = this.spawnCliWithArgsAndEnv(args, configEnv);

return await new Promise<string>((resolve, reject) => {
let stdoutData = "";
Expand Down Expand Up @@ -204,15 +230,15 @@ export class MirrordAPI {
* Spawn the mirrord cli with the given arguments.
* Used for reading/interacting while process still runs.
*/
private spawn(args: string[]): ChildProcessWithoutNullStreams {
return spawn(this.cliPath, args, { env: MirrordAPI.getEnv() });
private spawnCliWithArgsAndEnv(args: readonly string[], configEnv: EnvVars): ChildProcessWithoutNullStreams {
return spawn(this.cliPath, args, { env: MirrordAPI.getEnv(configEnv) });
}

/**
* Runs mirrord --version and returns the version string.
*/
async getBinaryVersion(): Promise<string | undefined> {
const stdout = await this.exec(["--version"]);
const stdout = await this.exec(["--version"], {});
// parse mirrord x.y.z
return stdout.split(" ")[1].trim();
}
Expand All @@ -227,7 +253,7 @@ export class MirrordAPI {
args.push('-f', configPath);
}

const stdout = await this.exec(args);
const stdout = await this.exec(args, {});

const targets: string[] = JSON.parse(stdout);
targets.sort();
Expand All @@ -250,10 +276,10 @@ export class MirrordAPI {
* Executes the `mirrord verify-config {configPath}` command, parsing its output into a
* `VerifiedConfig`.
*/
async verifyConfig(configPath: vscode.Uri | null): Promise<VerifiedConfig | undefined> {
async verifyConfig(configPath: vscode.Uri | null, configEnv: EnvVars): Promise<VerifiedConfig | undefined> {
if (configPath) {
const args = ['verify-config', '--ide', `${configPath.path}`];
const stdout = await this.exec(args);
const stdout = await this.exec(args, configEnv);

const verifiedConfig: VerifiedConfig = JSON.parse(stdout);
return verifiedConfig;
Expand All @@ -262,10 +288,13 @@ export class MirrordAPI {
}
}

// Run the extension execute sequence
// Creating agent and gathering execution runtime (env vars to set)
// Has 60 seconds timeout
async binaryExecute(target: string | null, configFile: string | null, executable: string | null): Promise<MirrordExecution> {
/**
* Runs the extension execute sequence, creating agent and gathering execution runtime while also
* setting env vars, both from system, and from `launch.json` (`configEnv`).
*
* Has 60 seconds timeout
*/
async binaryExecute(target: string | null, configFile: string | null, executable: string | null, configEnv: EnvVars): Promise<MirrordExecution> {
tickWaitlistCounter(!!target?.startsWith('deployment/'));
tickFeedbackCounter();

Expand All @@ -280,18 +309,9 @@ export class MirrordAPI {
reject("timeout");
}, 120 * 1000);

const args = ["ext"];
if (target) {
args.push("-t", target);
}
if (configFile) {
args.push("-f", configFile);
}
if (executable) {
args.push("-e", executable);
}
const args = makeMirrordArgs(target, configFile, executable);

const child = this.spawn(args);
const child = this.spawnCliWithArgsAndEnv(args, configEnv);

let stderrData = "";
child.stderr.on("data", (data) => stderrData += data.toString());
Expand Down
65 changes: 26 additions & 39 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ const DEFAULT_CONFIG = `{
}
`;

export type EnvVars = { [key: string]: string };

interface LaunchConfig {
name: string,
env?: { [key: string]: string };
env?: EnvVars;
}

/**
Expand Down Expand Up @@ -284,20 +286,6 @@ export class MirrordConfigManager {
vscode.window.showTextDocument(doc);
}

/**
* Resolves config file path specified in the launch config.
* @param folder workspace folder of the launch config
* @param path taken from the `MIRRORD_CONFIG_FILE` environment variable in launch config
* @returns config file Uri
*/
private static processPathFromLaunchConfig(folder: vscode.WorkspaceFolder | undefined, path: string): vscode.Uri {
if (folder) {
path = path.replace(/\$\{workspaceFolder\}/g, folder.uri.fsPath);
}

return vscode.Uri.file(path);
}

/**
* Used when preparing mirrord environment for the process.
* @param folder optional origin of the launch config
Expand All @@ -306,20 +294,17 @@ export class MirrordConfigManager {
*/
public async resolveMirrordConfig(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration): Promise<vscode.Uri | null> {
if (this.active) {
// User has selected a config (via active config button).
new NotificationBuilder()
.withMessage("using active mirrord configuration")
.withOpenFileAction(this.active)
.withDisableAction("promptUsingActiveConfig")
.info();
return this.active;
}

let launchConfig = config.env?.["MIRRORD_CONFIG_FILE"];
if (typeof launchConfig === "string") {
return MirrordConfigManager.processPathFromLaunchConfig(folder, launchConfig);
}

if (folder) {
} else if (config.env?.["MIRRORD_CONFIG_FILE"]) {
// Get the config path from the env var.
return vscode.Uri.parse(`file://${config.env?.["MIRRORD_CONFIG_FILE"]}`, true);
} else if (folder) {
let predefinedConfig = await MirrordConfigManager.getDefaultConfig(folder);
if (predefinedConfig) {
new NotificationBuilder()
Expand All @@ -328,24 +313,26 @@ export class MirrordConfigManager {
.withDisableAction("promptUsingDefaultConfig")
.warning();
return predefinedConfig;
} else {
return null;
}
} else {
folder = vscode.workspace.workspaceFolders?.[0];
if (!folder) {
throw new Error("mirrord requires an open folder in the workspace");
}
}

folder = vscode.workspace.workspaceFolders?.[0];
if (!folder) {
throw new Error("mirrord requires an open folder in the workspace");
}

let predefinedConfig = await MirrordConfigManager.getDefaultConfig(folder);
if (predefinedConfig) {
new NotificationBuilder()
.withMessage(`using a default mirrord config from folder ${folder.name}`)
.withOpenFileAction(predefinedConfig)
.withDisableAction("promptUsingDefaultConfig")
.warning();
return predefinedConfig;
let predefinedConfig = await MirrordConfigManager.getDefaultConfig(folder);
if (predefinedConfig) {
new NotificationBuilder()
.withMessage(`using a default mirrord config from folder ${folder.name} `)
.withOpenFileAction(predefinedConfig)
.withDisableAction("promptUsingDefaultConfig")
.warning();
return predefinedConfig;
} else {
return null;
}
}

return null;
}
}
Loading