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

Commit

Permalink
Merge pull request #13 from eclipse/CHE-11443
Browse files Browse the repository at this point in the history
CHE-11443 Implement the containers plugin
  • Loading branch information
olexii4 authored Jan 11, 2019
2 parents 560fa8a + f13929b commit e185f77
Show file tree
Hide file tree
Showing 11 changed files with 1,717 additions and 2,904 deletions.
7 changes: 7 additions & 0 deletions extensions/eclipse-che-theia-plugin/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@eclipse-che/api@^6.16.1":
version "6.16.1"
resolved "https://registry.yarnpkg.com/@eclipse-che/api/-/api-6.16.1.tgz#5b5e70285cf27d525df3752c938388e36f7925d6"
3 changes: 3 additions & 0 deletions plugins/containers-plugin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
lib/
node_modules/
*.theia
11 changes: 11 additions & 0 deletions plugins/containers-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# containers-plugin

Containers-tree plugin for Theia.

This plugin provides:

- List of containers with their status, where each container provides:

- List of servers (resource locator) if there is any;

- Ability to open a terminal within a selected container;
54 changes: 54 additions & 0 deletions plugins/containers-plugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "containers-plugin",
"publisher": "theia",
"keywords": [
"theia-plugin"
],
"version": "0.0.1",
"license": "EPL-2.0",
"files": [
"src"
],
"contributes": {
"viewsContainers": {
"right": [
{
"id": "containers",
"title": "Containers"
}
]
},
"views": {
"containers": [
{
"id": "containers",
"name": "Workspace"
}
]
}
},
"devDependencies": {
"@theia/plugin": "next",
"@theia/plugin-packager": "latest",
"@eclipse-che/plugin": "latest",
"rimraf": "2.6.2",
"typescript-formatter": "7.2.2",
"typescript": "2.9.2"
},
"dependencies": {
},
"scripts": {
"prepare": "yarn run clean && yarn run build",
"clean": "rimraf lib",
"format-code": "tsfmt -r",
"watch": "tsc -watch",
"compile": "tsc",
"build": "yarn run format-code && yarn run compile && theia:plugin pack"
},
"engines": {
"theiaPlugin": "next"
},
"theiaPlugin": {
"backend": "lib/containers-plugin.js"
}
}
25 changes: 25 additions & 0 deletions plugins/containers-plugin/src/containers-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*********************************************************************
* Copyright (c) 2018 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
**********************************************************************/

import { ContainersTreeDataProvider } from './containers-tree-data-provider';
import * as theia from '@theia/plugin';

export function start(context: theia.PluginContext) {
const treeDataProvider = new ContainersTreeDataProvider();
const treeDataDisposableFn = theia.Disposable.create(() => {
treeDataProvider.dispose();
});
context.subscriptions.push(treeDataDisposableFn);

theia.window.createTreeView('containers', { treeDataProvider });
}

export function stop() {
}
69 changes: 69 additions & 0 deletions plugins/containers-plugin/src/containers-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*********************************************************************
* Copyright (c) 2018 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
**********************************************************************/

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

export interface IContainer {
name: string;
status?: 'STARTING' | 'RUNNING' | 'STOPPED' | 'FAILED';
servers?: {
[serverRef: string]: {
url?: string;
}
};
}

export class ContainersService {
private _containers: Array<IContainer>;

constructor() {
this._containers = [];
}

async updateMachines(): Promise<void> {
const workspace = await che.workspace.getCurrentWorkspace();
if (!workspace) {
return Promise.reject('Failed to get workspace configuration');
}

const workspaceMachines = workspace!.runtime
&& workspace!.runtime!.machines
|| workspace!.config!.environments![workspace.config!.defaultEnv!].machines
|| {};

this._containers.length = 0;
Object.keys(workspaceMachines).forEach((machineName: string) => {
const machine = <{
servers?: {
[serverRef: string]: { url?: string; }
},
status?: 'STARTING' | 'RUNNING' | 'STOPPED' | 'FAILED';
}>workspaceMachines[machineName];
const container: IContainer = {
name: machineName,
status: machine.status
};
if (machine && machine.servers) {
container.servers = {};
Object.keys(machine.servers).forEach((serverName: string) => {
const server = machine!.servers![serverName]!;
if (server && server.url) {
container!.servers![serverName] = { url: server!.url };
}
});
}
this._containers.push(container);
});
}

get containers(): Array<IContainer> {
return this._containers;
}
}
158 changes: 158 additions & 0 deletions plugins/containers-plugin/src/containers-tree-data-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*********************************************************************
* Copyright (c) 2018 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
**********************************************************************/

import * as theia from '@theia/plugin';
import { ContainersService, IContainer } from './containers-service';

interface ITreeNodeItem {
id: string;
name: string;
tooltip: string;
iconPath?: string;
parentId?: string;
commandId?: string;
isExpanded?: boolean;
}

export class ContainersTreeDataProvider implements theia.TreeDataProvider<ITreeNodeItem> {
private ids: string[];
private treeNodeItems: ITreeNodeItem[];
private onDidChangeTreeDataEmitter: theia.EventEmitter<undefined>;

readonly onDidChangeTreeData: theia.Event<undefined>;

constructor() {
this.ids = [];
this.treeNodeItems = [];

this.onDidChangeTreeDataEmitter = new theia.EventEmitter<undefined>();
this.onDidChangeTreeData = this.onDidChangeTreeDataEmitter.event;

const containersService = new ContainersService();

this.updateContainersTreeData(containersService).then(() => {
this.onDidChangeTreeDataEmitter.fire();
});
}

private async updateContainersTreeData(containersService: ContainersService): Promise<void> {
this.ids.length = 0;
this.treeNodeItems.length = 0;
await containersService.updateMachines();
containersService.containers.forEach((container: IContainer) => {
const treeItem: ITreeNodeItem = {
id: this.getRandId(),
name: container.name,
tooltip: 'container name',
isExpanded: true
};
switch (container.status) {
case 'STARTING':
treeItem.iconPath = 'fa-circle medium-yellow';
treeItem.tooltip = 'container is STARTING';
break;
case 'RUNNING':
treeItem.iconPath = 'fa-circle medium-green';
treeItem.tooltip = 'container is RUNNING';
break;
case 'FAILED':
treeItem.iconPath = 'fa-circle medium-red';
treeItem.tooltip = 'container is FAILED';
break;
default:
treeItem.iconPath = 'fa-circle-o';
}
this.treeNodeItems.push(treeItem);
this.treeNodeItems.push({
id: this.getRandId(),
parentId: treeItem.id,
name: 'New terminal',
iconPath: 'fa-terminal medium-yellow',
tooltip: `open a new terminal for ${container.name}`,
commandId: `terminal-for-${container.name}-container:new`
});
const servers = container.servers;
if (!servers) {
return;
}
const serverKeys = Object.keys(servers);
if (!serverKeys.length) {
return;
}
const serversId = this.getRandId();
this.treeNodeItems.push({
id: serversId,
parentId: treeItem.id,
name: 'servers',
tooltip: 'servers',
isExpanded: true
});
serverKeys.forEach((serverName: string) => {
const server = servers[serverName];
if (!server) {
return;
}
const treeNodeItem: ITreeNodeItem = {
id: this.getRandId(),
parentId: serversId,
name: serverName,
iconPath: 'fa-info-circle medium-blue',
tooltip: server.url ? server.url : 'server'
};
if (server.url && server.url.startsWith('http')) {
treeNodeItem.name = ` [${serverName}](${server.url})`;
treeNodeItem.iconPath = 'fa-share medium-blue';
}
this.treeNodeItems.push(treeNodeItem);
});
});
}

private getRandId(): string {
let uniqueId = '';
for (let counter = 0; counter < 1000; counter++) {
uniqueId = `${('0000' + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4)}`;
if (this.ids.findIndex(id => id === uniqueId) === -1) {
break;
}
}
this.ids.push(uniqueId);
return uniqueId;
}

dispose(): void {
this.onDidChangeTreeDataEmitter.dispose();
}

getTreeItem(element: ITreeNodeItem): theia.TreeItem {
const treeItem: theia.TreeItem = {
label: element.name,
tooltip: element.tooltip
};
if (element.isExpanded) {
treeItem.collapsibleState = theia.TreeItemCollapsibleState.Expanded;
}
if (element.iconPath) {
treeItem.iconPath = element.iconPath;
}
if (element.commandId) {
treeItem.command = { id: element.commandId };
}
return treeItem;
}

getChildren(element?: ITreeNodeItem): ITreeNodeItem[] {
if (element) {
return this.treeNodeItems.filter(item => item.parentId === element.id);
} else {
return this.treeNodeItems.filter(item => item.parentId === undefined);
}
}
}
23 changes: 23 additions & 0 deletions plugins/containers-plugin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"strict": true,
"skipLibCheck": true,
"experimentalDecorators": true,
"noUnusedLocals": true,
"emitDecoratorMetadata": true,
"downlevelIteration": true,
"module": "commonjs",
"moduleResolution": "node",
"target": "es5",
"lib": [
"es6",
"webworker"
],
"sourceMap": true,
"rootDir": "src",
"outDir": "lib"
},
"include": [
"src"
]
}
19 changes: 19 additions & 0 deletions plugins/containers-plugin/tsfmt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"baseIndentSize": 0,
"newLineCharacter": "\n",
"indentSize": 4,
"tabSize": 4,
"indentStyle": 4,
"convertTabsToSpaces": true,
"insertSpaceAfterCommaDelimiter": true,
"insertSpaceAfterSemicolonInForStatements": true,
"insertSpaceBeforeAndAfterBinaryOperators": true,
"insertSpaceAfterKeywordsInControlFlowStatements": true,
"insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
"insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,
"insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,
"insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false,
"placeOpenBraceOnNewLineForFunctions": false,
"placeOpenBraceOnNewLineForControlBlocks": false
}

Loading

0 comments on commit e185f77

Please sign in to comment.