Skip to content

Commit 9e03220

Browse files
msivasubramaniaanvrubezhny
authored andcommitted
Replaced odo run command
Fixes: #5776 Authored-by: msivasubramaniaan <msivasub@redhat.com> Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
1 parent 85ddbcb commit 9e03220

24 files changed

Lines changed: 528 additions & 84 deletions

src/cli.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,9 @@ import * as cp from 'child_process';
88
import { CommandText } from './base/command';
99
import { ToolsConfig } from './tools';
1010
import { ChildProcessUtil, CliExitData } from './util/childProcessUtil';
11-
import { hash } from './util/utils';
11+
import { ExecutionContext } from './util/utils';
1212
import { VsCommandError } from './vscommand';
1313

14-
export class ExecutionContext extends Map<string, any> {
15-
public static key(value: string): string {
16-
return hash(value);
17-
}
18-
}
19-
2014
export class CliChannel {
2115

2216
private static telemetrySettings = new VSCodeSettings();

src/devfile-registry/devfileRegistryWrapper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import { get as httpGet } from 'http';
66
import { get as httpsGet } from 'https';
77
import * as YAML from 'js-yaml';
8-
import { ExecutionContext } from '../cli';
98
import { Registry } from '../odo/componentType';
109
import { OdoPreference } from '../odo/odoPreference';
10+
import { ExecutionContext } from '../util/utils';
1111
import { DevfileData, DevfileInfo } from './devfileInfo';
1212

1313
export const DEVFILE_VERSION_LATEST: string = 'latest';

src/devfile/commandResolver.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
import { Command, Data } from '../odo/componentTypeDescription';
6+
7+
export class CommandResolver {
8+
public static getCommand(devfile: Data, commandId: string): Command {
9+
const command = devfile.commands.find(
10+
(c) => c.id.toLowerCase() === commandId.toLowerCase(),
11+
);
12+
13+
if (!command) {
14+
throw new Error(`Command '${commandId}' not found`);
15+
}
16+
17+
return command;
18+
}
19+
20+
public static getAllCommandsMap(devfile: Data): Map<string, Command> {
21+
const map = new Map<string, Command>();
22+
23+
for (const command of devfile.commands) {
24+
map.set(command.id.toLowerCase(), command);
25+
}
26+
27+
return map;
28+
}
29+
}

src/devfile/compositeCommand.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
6+
import { ComponentWorkspaceFolder } from '../odo/workspace';
7+
import { Command } from '../odo/componentTypeDescription';
8+
import { DevfileCommandRunner } from './devfileCommandRunner';
9+
10+
export class CompositeCommand {
11+
12+
public static async execute(
13+
componentFolder: ComponentWorkspaceFolder,
14+
command: Command,
15+
): Promise<void> {
16+
17+
for (const childId of command.composite.commands) {
18+
await DevfileCommandRunner.execute(
19+
componentFolder,
20+
childId,
21+
);
22+
}
23+
}
24+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
6+
import { ComponentWorkspaceFolder } from '../odo/workspace';
7+
import { Command } from '../odo/componentTypeDescription';
8+
import { CommandResolver } from './commandResolver';
9+
import { ExecCommandExecutor } from './execCommand';
10+
11+
export class DevfileCommandRunner {
12+
public static async execute(
13+
componentFolder: ComponentWorkspaceFolder,
14+
commandId: string,
15+
): Promise<void> {
16+
const devfile = componentFolder.component.devfileData.devfile;
17+
18+
const command = CommandResolver.getCommand(devfile, commandId);
19+
20+
await this.executeCommand(componentFolder, command);
21+
}
22+
23+
private static async executeCommand(
24+
componentFolder: ComponentWorkspaceFolder,
25+
command: Command,
26+
): Promise<void> {
27+
if (command.exec) {
28+
await ExecCommandExecutor.execute(componentFolder, command.id, command.exec);
29+
30+
return;
31+
}
32+
33+
if (command.composite) {
34+
const devfile = componentFolder.component.devfileData.devfile;
35+
36+
const commandMap = CommandResolver.getAllCommandsMap(devfile);
37+
38+
const children = command.composite.commands.map((id) => {
39+
const child = commandMap.get(id.toLowerCase());
40+
41+
if (!child) {
42+
throw new Error(`Command '${id}' not found`);
43+
}
44+
45+
return child;
46+
});
47+
48+
const isParallel =
49+
(
50+
command.composite as {
51+
parallel?: boolean;
52+
}
53+
).parallel === true;
54+
55+
if (isParallel) {
56+
await Promise.all(
57+
children.map((child) => this.executeCommand(componentFolder, child)),
58+
);
59+
} else {
60+
for (const child of children) {
61+
await this.executeCommand(componentFolder, child);
62+
}
63+
}
64+
65+
return;
66+
}
67+
68+
throw new Error(`Unsupported command '${command.id}'`);
69+
}
70+
}

src/devfile/execCommand.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
6+
import { CommandOption, CommandText } from '../base/command';
7+
import { Oc } from '../oc/ocWrapper';
8+
import { Exec } from '../odo/componentTypeDescription';
9+
import { ComponentWorkspaceFolder } from '../odo/workspace';
10+
import { OpenShiftTerminalManager } from '../webview/openshift-terminal/openShiftTerminal';
11+
import { DevfileResolver } from './devfileResolver';
12+
import { VariableResolver } from './variableResolver';
13+
14+
export class ExecCommandExecutor {
15+
public static async execute(
16+
componentFolder: ComponentWorkspaceFolder,
17+
commandId: string,
18+
exec: Exec,
19+
): Promise<void> {
20+
const rawDevfile = componentFolder.component.devfileData.devfile;
21+
22+
const resolver = new DevfileResolver();
23+
const devfile = await resolver.resolve(rawDevfile);
24+
25+
const resolvedExec = VariableResolver.resolveExec(devfile, exec);
26+
27+
const componentName = devfile.metadata.name;
28+
29+
const podName = await Oc.Instance.getComponentPod(componentName);
30+
31+
const command = new CommandText('oc', 'exec', [
32+
new CommandOption(podName),
33+
new CommandOption('-c'),
34+
new CommandOption(resolvedExec.component),
35+
new CommandOption('--'),
36+
new CommandOption('sh'),
37+
new CommandOption('-c'),
38+
new CommandOption(`cd ${resolvedExec.workingDir} && ${resolvedExec.commandLine}`),
39+
]);
40+
41+
void OpenShiftTerminalManager.getInstance().createTerminal(
42+
command,
43+
`Component ${componentName}: Run '${commandId}' Command`,
44+
componentFolder.contextPath,
45+
);
46+
}
47+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
6+
import { Command } from '../odo/componentTypeDescription';
7+
import { ComponentWorkspaceFolder } from '../odo/workspace';
8+
import { DevfileCommandRunner } from './devfileCommandRunner';
9+
10+
export class ParallelCompositeCommand {
11+
12+
public static async execute(
13+
componentFolder: ComponentWorkspaceFolder,
14+
command: Command,
15+
): Promise<void> {
16+
17+
await Promise.all(
18+
command.composite.commands.map(
19+
childId =>
20+
DevfileCommandRunner.execute(
21+
componentFolder,
22+
childId,
23+
),
24+
),
25+
);
26+
}
27+
}

src/devfile/variableResolver.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
6+
import { Container, Data, Exec } from '../odo/componentTypeDescription';
7+
8+
export class VariableResolver {
9+
private static readonly VARIABLE_REGEX = /\$\{([^}]+)\}/g;
10+
11+
public static resolveExec(devfile: Data, exec: Exec): Exec {
12+
return {
13+
...exec,
14+
workingDir: this.resolveValue(devfile, exec.workingDir ?? '/projects', exec.component),
15+
commandLine: this.resolveValue(devfile, exec.commandLine, exec.component),
16+
};
17+
}
18+
19+
public static resolveValue(devfile: Data, value: string, componentName?: string): string {
20+
if (!value) {
21+
return value;
22+
}
23+
24+
return value.replace(this.VARIABLE_REGEX, (_, variable) =>
25+
this.resolveVariable(devfile, variable, componentName),
26+
);
27+
}
28+
29+
private static resolveVariable(
30+
devfile: Data,
31+
variable: string,
32+
componentName?: string,
33+
): string {
34+
if (variable === 'PROJECT_SOURCE') {
35+
return '/projects';
36+
}
37+
38+
if (componentName) {
39+
const component = devfile.components.find((c) => c.name === componentName);
40+
41+
const container = component?.container;
42+
43+
const envValue = this.findEnvValue(container, variable);
44+
45+
if (envValue) {
46+
return envValue;
47+
}
48+
}
49+
50+
return process.env[variable] ?? `\${${variable}}`;
51+
}
52+
53+
private static findEnvValue(
54+
container: Container | undefined,
55+
variable: string,
56+
): string | undefined {
57+
const env = (
58+
container as unknown as {
59+
env?: {
60+
name: string;
61+
value: string;
62+
}[];
63+
}
64+
)?.env;
65+
66+
return env?.find((e) => e.name === variable)?.value;
67+
}
68+
}

src/explorer.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import {
2525
workspace
2626
} from 'vscode';
2727
import { CommandOption, CommandText } from './base/command';
28-
import { ExecutionContext } from './cli';
2928
import * as Helm from './helm/helm';
3029
import { HelmRepo } from './helm/helmChartType';
3130
import { getOutputFormat, helmfsUri, kubefsUri } from './k8s/vfs/kuberesources.utils';
@@ -37,7 +36,7 @@ import { getKubeConfigFiles, getNamespaceKind, isOpenShiftCluster, KubeConfigInf
3736
import { LoginUtil } from './util/loginUtil';
3837
import { Platform } from './util/platform';
3938
import { Progress } from './util/progress';
40-
import { imagePath } from './util/utils';
39+
import { ExecutionContext, imagePath } from './util/utils';
4140
import { FileContentChangeNotifier, WatchUtil } from './util/watch';
4241
import { vsCommand } from './vscommand';
4342
import { CustomResourceDefinitionStub, K8sResourceKind } from './webview/common/createServiceTypes';

src/k8s/vfs/kuberesources.utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import * as _ from 'lodash';
99
import { Diagnostic, DiagnosticSeverity, FileStat, FileType, Range, TextDocument, Uri, workspace } from 'vscode';
1010
import { Document, isMap, isPair, isScalar, isSeq, Pair, parse, ParsedNode, parseDocument, stringify } from 'yaml';
1111
import { CommandOption, CommandText } from '../../base/command';
12-
import { CliChannel, ExecutionContext } from '../../cli';
12+
import { CliChannel } from '../../cli';
1313
import { Oc } from '../../oc/ocWrapper';
14-
import { YAML_STRINGIFY_OPTIONS } from '../../util/utils';
14+
import { ExecutionContext, YAML_STRINGIFY_OPTIONS } from '../../util/utils';
1515

1616
export const K8S_RESOURCE_SCHEME = 'osmsx'; // Changed from 'k8smsx' to 'osmsx' to not make a conflict with k8s extension
1717
export const K8S_RESOURCE_SCHEME_READONLY = 'osmsxro'; // Changed from 'k8smsxro' to 'osmsxro' to not make a conflict with k8s extension

0 commit comments

Comments
 (0)