Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Commit

Permalink
feat(task-plugin): bump to devfile 2.0 API
Browse files Browse the repository at this point in the history
Change-Id: Ib64a9a1b8e4f15ffba869e79bfe7aa1aa0a87b00
Signed-off-by: Florent Benoit <fbenoit@redhat.com>
  • Loading branch information
benoitf committed Mar 12, 2021
1 parent 6addea2 commit 67e7abd
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 194 deletions.
1 change: 1 addition & 0 deletions plugins/task-plugin/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ dist/
lib/
node_modules/
*.theia
coverage
22 changes: 22 additions & 0 deletions plugins/task-plugin/__mocks__/@eclipse-che/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**********************************************************************
* Copyright (c) 2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

/* eslint-disable @typescript-eslint/no-explicit-any */
const chePlugin: any = {};
chePlugin.devfile = {
get: jest.fn(),
getComponentStatuses: jest.fn(),
};

chePlugin.endpoint = {
getEndpointsByType: jest.fn(),
};

module.exports = chePlugin;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

describe('no-op', function () {
it('no-op', function () {});
});
/* eslint-disable @typescript-eslint/no-explicit-any */
const theiaPlugin: any = {};

theiaPlugin.window = {
createOutputChannel: jest.fn()
};
module.exports = theiaPlugin;
103 changes: 19 additions & 84 deletions plugins/task-plugin/src/che-workspace-client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2019-2020 Red Hat, Inc.
* Copyright (c) 2019-2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -9,18 +9,14 @@
***********************************************************************/

import * as che from '@eclipse-che/plugin';
import * as theia from '@theia/plugin';

import { che as cheApi } from '@eclipse-che/api';
import { injectable } from 'inversify';

const TERMINAL_SERVER_TYPE = 'terminal';

export const RECIPE_CONTAINER_SOURCE = 'recipe';
export const CONTAINER_SOURCE_ATTRIBUTE = 'source';

export interface WorkspaceContainer extends cheApi.workspace.Machine {
name: string;
}
export interface WorkspaceContainer extends che.devfile.DevfileComponentStatus {}

@injectable()
export class CheWorkspaceClient {
Expand All @@ -30,57 +26,8 @@ export class CheWorkspaceClient {
return workspace.links;
}

/** Returns array of containers' names for the current workspace. */
async getContainersNames(): Promise<string[]> {
const containerNames: string[] = [];

try {
const containers = await this.getMachines();
for (const containerName in containers) {
if (containers.hasOwnProperty(containerName)) {
containerNames.push(containerName);
}
}
} catch (error) {
} finally {
return containerNames;
}
}

async getMachines(): Promise<{ [attrName: string]: cheApi.workspace.Machine }> {
const workspace = await this.getCurrentWorkspace();
const runtime = workspace.runtime;
if (!runtime) {
throw new Error('Workspace is not running.');
}

const machines = runtime.machines;
if (!machines) {
throw new Error('No machines for current workspace is found.');
}
return machines;
}

async getContainers(): Promise<WorkspaceContainer[]> {
const containers: WorkspaceContainer[] = [];
try {
const workspace = await this.getCurrentWorkspace();

if (workspace.runtime && workspace.runtime.machines) {
const machines = workspace.runtime.machines;
for (const machineName in machines) {
if (!machines.hasOwnProperty(machineName)) {
continue;
}
const container: WorkspaceContainer = { name: machineName, ...machines[machineName] };
containers.push(container);
}
}
} catch (e) {
throw new Error('Unable to get list workspace containers. Cause: ' + e);
}

return containers;
async getComponentStatuses(): Promise<che.devfile.DevfileComponentStatus[]> {
return che.devfile.getComponentStatuses();
}

async getCommands(): Promise<cheApi.workspace.Command[]> {
Expand All @@ -105,34 +52,22 @@ export class CheWorkspaceClient {
}

async getMachineExecServerURL(): Promise<string> {
const machineExecServer = await this.getMachineExecServer();
if (!machineExecServer) {
throw new Error(`No server with type ${TERMINAL_SERVER_TYPE} found.`);
}
if (!machineExecServer.attributes!.port) {
throw new Error('No machine-exec-server attributes.port found');
}
return `ws://127.0.0.1:${machineExecServer.attributes!.port}`;
const machineExecEndpoint = await this.getMachineExecEndpoint();
const outputChannelTaskPlugin = theia.window.createOutputChannel('task-plugin-ref');
const port = machineExecEndpoint.attributes?.port || machineExecEndpoint.attributes?.targetPort;
outputChannelTaskPlugin.appendLine(
`port is ${port} and machineExecEndpoint is ${JSON.stringify(machineExecEndpoint, undefined, 2)}`
);
return `ws://127.0.0.1:${port}`;
}

protected async getMachineExecServer(): Promise<cheApi.workspace.Server | undefined> {
const machines = await this.getMachines();
for (const machineName in machines) {
if (!machines.hasOwnProperty(machineName)) {
continue;
}
const servers = machines[machineName].servers!;
for (const serverName in servers) {
if (!servers.hasOwnProperty(serverName)) {
continue;
}

const serverAttributes = servers[serverName].attributes;
if (serverAttributes && serverAttributes['type'] === TERMINAL_SERVER_TYPE) {
return servers[serverName];
}
}
protected async getMachineExecEndpoint(): Promise<che.endpoint.ExposedEndpoint> {
const terminalEndpoints = await che.endpoint.getEndpointsByType(TERMINAL_SERVER_TYPE);
const outputChannel = theia.window.createOutputChannel('task-plugin');
outputChannel.appendLine(`terminalEndpoints are ${JSON.stringify(terminalEndpoints, undefined, 2)}`);
if (terminalEndpoints.length === 1) {
return terminalEndpoints[0];
}
return undefined;
throw new Error(`Unable to find terminal with type ${TERMINAL_SERVER_TYPE}: Found: ${terminalEndpoints}`);
}
}
23 changes: 5 additions & 18 deletions plugins/task-plugin/src/machine/machines-picker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2019-2020 Red Hat, Inc.
* Copyright (c) 2019-2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -8,12 +8,7 @@
* SPDX-License-Identifier: EPL-2.0
***********************************************************************/

import {
CONTAINER_SOURCE_ATTRIBUTE,
CheWorkspaceClient,
RECIPE_CONTAINER_SOURCE,
WorkspaceContainer,
} from '../che-workspace-client';
import { CheWorkspaceClient, WorkspaceContainer } from '../che-workspace-client';
import { QuickPickItem, window } from '@theia/plugin';
import { inject, injectable } from 'inversify';

Expand Down Expand Up @@ -60,7 +55,7 @@ export class MachinesPicker {
}

private async pickContainerFromClient(): Promise<string> {
const containers = await this.cheWorkspaceClient.getContainers();
const containers = await this.cheWorkspaceClient.getComponentStatuses();

if (containers.length === 1) {
return Promise.resolve(containers[0].name);
Expand All @@ -74,8 +69,8 @@ export class MachinesPicker {
private toQuickPickItems(containers: WorkspaceContainer[]): QuickPickItem[] {
const items: QuickPickItem[] = [];

const devContainers = containers.filter(container => this.isDevContainer(container));
const toolingContainers = containers.filter(container => !this.isDevContainer(container));
const devContainers = containers.filter(container => container.isUser);
const toolingContainers = containers.filter(container => !container.isUser);

items.push(
...devContainers.map(
Expand Down Expand Up @@ -109,12 +104,4 @@ export class MachinesPicker {

return items;
}

private isDevContainer(container: WorkspaceContainer): boolean {
return (
container.attributes !== undefined &&
(!container.attributes[CONTAINER_SOURCE_ATTRIBUTE] ||
container.attributes[CONTAINER_SOURCE_ATTRIBUTE] === RECIPE_CONTAINER_SOURCE)
);
}
}
17 changes: 6 additions & 11 deletions plugins/task-plugin/src/task/backward-compatibility.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2019-2020 Red Hat, Inc.
* Copyright (c) 2019-2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -13,9 +13,7 @@ import * as che from '@eclipse-che/plugin';
import { inject, injectable } from 'inversify';

import { CHE_TASK_TYPE } from './task-protocol';
import { COMPONENT_ATTRIBUTE } from '../machine/machines-picker';
import { CheWorkspaceClient } from '../che-workspace-client';
import { getAttribute } from '../utils';

/** Contains logic to provide backward compatibility. */
@injectable()
Expand Down Expand Up @@ -61,7 +59,7 @@ export class BackwardCompatibilityResolver {
return configs;
}

const containers = await this.cheWorkspaceClient.getMachines();
const containers = await this.cheWorkspaceClient.getComponentStatuses();
for (const config of configs) {
if (config.type !== CHE_TASK_TYPE) {
continue;
Expand All @@ -76,14 +74,11 @@ export class BackwardCompatibilityResolver {
target.containerName = undefined;
target.component = '';

if (!containers.hasOwnProperty(containerName)) {
const matchingComponent = containers.find(component => component.name === containerName);
if (!matchingComponent) {
continue;
}

const container = containers[containerName];
const component = getAttribute(COMPONENT_ATTRIBUTE, container.attributes);
if (component) {
target.component = component;
} else {
target.component = matchingComponent.name;
}
}
return configs;
Expand Down
58 changes: 7 additions & 51 deletions plugins/task-plugin/src/task/che-task-provider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2019-2020 Red Hat, Inc.
* Copyright (c) 2019-2021 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -11,13 +11,11 @@
import * as che from '@eclipse-che/plugin';

import { CHE_TASK_TYPE, CheTaskDefinition, Target } from './task-protocol';
import { COMPONENT_ATTRIBUTE, MachinesPicker } from '../machine/machines-picker';
import { ShellExecution, Task } from '@theia/plugin';
import { inject, injectable } from 'inversify';

import { CheWorkspaceClient } from '../che-workspace-client';
import { che as cheApi } from '@eclipse-che/api';
import { getAttribute } from '../utils';
import { MachinesPicker } from '../machine/machines-picker';

/** Reads the commands from the current Che workspace and provides it as Task Configurations. */
@injectable()
Expand Down Expand Up @@ -49,7 +47,11 @@ export class CheTaskProvider {
resultTarget.workspaceId = await this.cheWorkspaceClient.getWorkspaceId();
}

resultTarget.containerName = await this.getContainerName(target);
if (target && target.component) {
resultTarget.component = target.component;
} else {
resultTarget.component = await this.machinePicker.pick();
}

if (target && target.workingDir) {
resultTarget.workingDir = await che.variables.resolve(target.workingDir);
Expand All @@ -71,50 +73,4 @@ export class CheTaskProvider {
execution: execution,
};
}

private async getContainerName(target?: Target): Promise<string> {
if (!target) {
return this.machinePicker.pick();
}

const containers = await this.cheWorkspaceClient.getMachines();

const containerName = target.containerName;
if (containerName && containers.hasOwnProperty(containerName)) {
return containerName;
}

return (await this.getContainerNameByComponent(target.component, containers)) || this.machinePicker.pick();
}

private async getContainerNameByComponent(
targetComponent: string | undefined,
containers: { [attrName: string]: cheApi.workspace.Machine }
): Promise<string | undefined> {
if (!targetComponent) {
return undefined;
}

const names = [];
for (const containerName in containers) {
if (!containers.hasOwnProperty(containerName)) {
continue;
}

const container = containers[containerName];
const component = getAttribute(COMPONENT_ATTRIBUTE, container.attributes);
if (component && component === targetComponent) {
names.push(containerName);
}
}

if (names.length === 1) {
return names[0];
}

if (names.length > 1) {
return this.machinePicker.pick(names);
}
return undefined;
}
}
Loading

0 comments on commit 67e7abd

Please sign in to comment.