Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions tools/build/src/devfile/devfile-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**********************************************************************
* 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
***********************************************************************/
import { ContainerModule, interfaces } from 'inversify';

import { MetaYamlToDevfileYaml } from './meta-yaml-to-devfile-yaml';

const devfileModule = new ContainerModule((bind: interfaces.Bind) => {
bind(MetaYamlToDevfileYaml).toSelf().inSingletonScope();
});

export { devfileModule };
167 changes: 167 additions & 0 deletions tools/build/src/devfile/meta-yaml-to-devfile-yaml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/**********************************************************************
* 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
***********************************************************************/

import { injectable } from 'inversify';

/**
* Convert meta.yaml into a devfile 2.0 syntax
*/
@injectable()
export class MetaYamlToDevfileYaml {
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
componentsFromContainer(container: any): any[] {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const components: any[] = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const component: any = {
name: container.name,
container: {
image: container.image,
},
};
if (container.command) {
component.container.args = container.command;
}
if (container.env) {
component.container.env = container.env;
}
if (container.volumes) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
component.container.volumeMounts = container.volumes.map((volume: any) => ({
name: volume.name,
path: volume.mountPath,
}));

// add volume components
// eslint-disable-next-line @typescript-eslint/no-explicit-any
container.volumes.map((volume: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const volumeComponent: any = {
name: volume.name,
volume: {},
};
if (volume.ephemeral === true) {
volumeComponent.volume.ephemeral = true;
}
components.push(volumeComponent);
});
}
if (container.mountSources) {
component.container.mountSources = container.mountSources;
}
if (container.memoryLimit) {
component.container.memoryLimit = container.memoryLimit;
}
if (container.memoryRequest) {
component.container.memoryRequest = container.memoryRequest;
}
if (container.cpuLimit) {
component.container.cpuLimit = container.cpuLimit;
}
if (container.cpuRequest) {
component.container.cpuRequest = container.cpuRequest;
}

components.push(component);

// replace 127.0.0.1 by 0.0.0.0
return components.map(iteratingComponent =>
JSON.parse(JSON.stringify(iteratingComponent).replace(/127\.0\.0\.1/g, '0.0.0.0'))
);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types
convert(metaYaml: any): any | undefined {
// do not handle VS Code extensions as they can't be converted into devfile 2.0
if (!metaYaml || metaYaml.type === 'VS Code extension') {
return;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const devfileYaml: any = {
schemaVersion: '2.1.0',
metadata: {
name: metaYaml.displayName,
},
};

// for each container, add a component
const metaYamlSpec = metaYaml.spec;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let components: any[] = [];
if (metaYamlSpec.containers && metaYamlSpec.containers.length === 1) {
// handle only one container from meta.yaml
const container = metaYamlSpec.containers[0];

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const componentsFromContainer: any[] = this.componentsFromContainer(container);
// add all endpoints
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const endpoints: any[] = [];
if (metaYamlSpec.endpoints && metaYamlSpec.endpoints.length > 0) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
metaYamlSpec.endpoints.forEach((endpoint: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const devfileEndpoint: any = {
name: endpoint.name,
attributes: endpoint.attributes,
};
devfileEndpoint.targetPort = endpoint.targetPort;
if (endpoint.public === true) {
devfileEndpoint.exposure = 'public';
}

// if it's secured, remove secure option for now
if (devfileEndpoint.attributes && devfileEndpoint.attributes.secure === true) {
devfileEndpoint.secure = false;
delete devfileEndpoint.attributes['secure'];
}

// move protocol upper than inside attributes
if (devfileEndpoint.attributes && devfileEndpoint.attributes.protocol) {
devfileEndpoint.protocol = devfileEndpoint.attributes.protocol;
delete devfileEndpoint.attributes['protocol'];
}

endpoints.push(devfileEndpoint);
});
}
// last component is the container component
componentsFromContainer[componentsFromContainer.length - 1].container.endpoints = endpoints;
components = components.concat(componentsFromContainer);
}
if (metaYamlSpec.initContainers && metaYamlSpec.initContainers.length === 1) {
// handle only one container from meta.yaml
const initContainer = metaYamlSpec.initContainers[0];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const componentsFromContainer: any[] = this.componentsFromContainer(initContainer);

// add a command
const commands = devfileYaml.commands || [];
commands.push({
id: 'init-container-command',
apply: {
component: componentsFromContainer[componentsFromContainer.length - 1].name,
},
});
devfileYaml.commands = commands;

// add event
const events = devfileYaml.events || {};
const preStartEvents = events.preStart || [];
preStartEvents.push('init-container-command');
events.preStart = preStartEvents;
devfileYaml.events = events;
components = components.concat(componentsFromContainer);
}
devfileYaml.components = components;
return devfileYaml;
}
}
2 changes: 2 additions & 0 deletions tools/build/src/inversify-binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Container } from 'inversify';
import { chePluginsModule } from './che-plugin/che-plugins-module';
import { cheTheiaPluginModule } from './che-theia-plugin/che-theia-plugin-module';
import { commonModule } from './common/common-module';
import { devfileModule } from './devfile/devfile-module';
import { editorModule } from './editor/editor-module';
import { extensionsModule } from './extensions/extension-module';
import { featuredModule } from './featured/featured-module';
Expand Down Expand Up @@ -51,6 +52,7 @@ export class InversifyBinding {
this.container.load(commonModule);
this.container.load(chePluginsModule);
this.container.load(cheTheiaPluginModule);
this.container.load(devfileModule);
this.container.load(editorModule);
this.container.load(extensionsModule);
this.container.load(featuredModule);
Expand Down
14 changes: 11 additions & 3 deletions tools/build/src/meta-yaml/index-writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ export class IndexWriter {
@named('OUTPUT_ROOT_DIRECTORY')
private outputRootDirectory: string;

getLinks(plugin: MetaYamlPluginInfo): { self: string; devfile?: string } {
const links: { self: string; devfile?: string } = {
self: `/v3/plugins/${plugin.id}`,
};
if (plugin.type === 'Che Editor' || plugin.type === 'Che Plugin') {
links.devfile = `/v3/plugins/${plugin.id}/devfile.yaml`;
}
return links;
}

async write(generatedMetaYamlPluginInfos: MetaYamlPluginInfo[]): Promise<void> {
const v3PluginsFolder = path.resolve(this.outputRootDirectory, 'v3', 'plugins');
await fs.ensureDir(v3PluginsFolder);
Expand All @@ -33,9 +43,7 @@ export class IndexWriter {
id: plugin.id,
description: plugin.description,
displayName: plugin.displayName,
links: {
self: `/v3/plugins/${plugin.id}`,
},
links: this.getLinks(plugin),
name: plugin.name,
publisher: plugin.publisher,
type: plugin.type,
Expand Down
11 changes: 10 additions & 1 deletion tools/build/src/meta-yaml/meta-yaml-writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import * as path from 'path';
import { inject, injectable, named } from 'inversify';

import { MetaYamlPluginInfo } from './meta-yaml-plugin-info';
import { MetaYamlToDevfileYaml } from '../devfile/meta-yaml-to-devfile-yaml';

@injectable()
export class MetaYamlWriter {
Expand All @@ -27,6 +28,9 @@ export class MetaYamlWriter {
@named('EMBED_VSIX')
private embedVsix: boolean;

@inject(MetaYamlToDevfileYaml)
private metaYamlToDevfileYaml: MetaYamlToDevfileYaml;

public static readonly DEFAULT_ICON = '/v3/images/eclipse-che-logo.png';

convertIdToPublisherAndName(id: string): [string, string] {
Expand Down Expand Up @@ -155,9 +159,14 @@ export class MetaYamlWriter {
metaYamlPluginGenerated.push(generated);

const pluginPath = path.resolve(pluginsFolder, computedId, version, 'meta.yaml');

await fs.ensureDir(path.dirname(pluginPath));
promises.push(fs.writeFile(pluginPath, yamlString));
const devfileYaml = this.metaYamlToDevfileYaml.convert(metaYaml);
if (devfileYaml) {
const devfilePath = path.resolve(pluginsFolder, computedId, version, 'devfile.yaml');
const devfileYamlString = jsyaml.safeDump(devfileYaml, { lineWidth: 120 });
promises.push(fs.writeFile(devfilePath, devfileYamlString));
}
})
);
return Promise.all(promises);
Expand Down
109 changes: 109 additions & 0 deletions tools/build/tests/_data/meta/che-theia-meta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
apiVersion: v2
publisher: eclipse
name: che-theia
version: next
type: Che Editor
displayName: theia-ide
title: Eclipse Theia development version.
description: 'Eclipse Theia, get the latest release each day.'
icon: /v3/images/eclipse-che-logo.png
category: Editor
repository: 'https://github.com/eclipse/che-theia'
firstPublicationDate: '2019-03-07'
latestUpdateDate: '2021-02-19'
spec:
endpoints:
- name: theia
public: true
targetPort: 3100
attributes:
protocol: http
type: ide
secure: true
cookiesAuthEnabled: true
discoverable: false
- name: webviews
public: true
targetPort: 3100
attributes:
protocol: http
type: webview
secure: true
cookiesAuthEnabled: true
discoverable: false
unique: true
- name: mini-browser
public: true
targetPort: 3100
attributes:
protocol: http
type: mini-browser
secure: true
cookiesAuthEnabled: true
discoverable: false
unique: true
- name: theia-dev
public: true
targetPort: 3130
attributes:
protocol: http
type: ide-dev
discoverable: false
- name: theia-redirect-1
public: true
targetPort: 13131
attributes:
protocol: http
discoverable: false
- name: theia-redirect-2
public: true
targetPort: 13132
attributes:
protocol: http
discoverable: false
- name: theia-redirect-3
public: true
targetPort: 13133
attributes:
protocol: http
discoverable: false
containers:
- name: theia-ide
image: 'quay.io/eclipse/che-theia:next'
env:
- name: THEIA_PLUGINS
value: 'local-dir:///plugins'
- name: HOSTED_PLUGIN_HOSTNAME
value: 0.0.0.0
- name: HOSTED_PLUGIN_PORT
value: '3130'
- name: THEIA_HOST
value: 127.0.0.1
mountSources: true
ports:
- exposedPort: 3100
- exposedPort: 3130
- exposedPort: 13131
- exposedPort: 13132
- exposedPort: 13133
memoryLimit: 512M
memoryRequest: 50M
cpuLimit: 1500m
cpuRequest: 100m
volumes:
- name: plugins
mountPath: /plugins
- name: theia-local
mountPath: /home/theia/.theia
initContainers:
- name: remote-runtime-injector
image: 'quay.io/eclipse/che-theia-endpoint-runtime-binary:next'
env:
- name: PLUGIN_REMOTE_ENDPOINT_EXECUTABLE
value: /remote-endpoint/plugin-remote-endpoint
- name: REMOTE_ENDPOINT_VOLUME_NAME
value: remote-endpoint
volumes:
- name: remote-endpoint
mountPath: /remote-endpoint
ephemeral: true
9 changes: 9 additions & 0 deletions tools/build/tests/_data/meta/container-minimal-endpoint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
displayName: minimal-endpoint
type: Che Plugin
spec:
endpoints:
- name: www
targetPort: 3100
containers:
- name: minimal-endpoint
image: 'quay.io/minimal-endpoint'
6 changes: 6 additions & 0 deletions tools/build/tests/_data/meta/container-no-endpoints.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
displayName: no-endpoint
type: Che Plugin
spec:
containers:
- name: no-endpoint
image: 'quay.io/no-endpoint'
Loading