From 33ac2a35e7b2a822a63ec04d398cdcd75e0dbdad Mon Sep 17 00:00:00 2001 From: Oleksii Orel Date: Fri, 19 Aug 2022 03:47:13 +0300 Subject: [PATCH] feat: provides OpenVSX CheCluster URL to user containers Signed-off-by: Oleksii Orel --- .../src/api/serverConfigApi.ts | 2 + .../services/api/serverConfigApi.ts | 4 ++ .../src/devworkspace-client/types/index.ts | 10 ++- .../src/services/bootstrap/index.ts | 9 ++- .../serverConfigApi.ts | 17 +++--- .../devWorkspaceClient.create.spec.ts | 5 ++ .../devWorkspaceClient.editorUpdate.spec.ts | 4 ++ .../devworkspace/devWorkspaceClient.ts | 61 +++++++++++++------ .../__tests__/index.spec.ts | 1 + .../ServerConfig/__tests__/index.spec.ts | 1 + .../src/store/ServerConfig/index.ts | 13 +--- .../src/store/ServerConfig/selectors.ts | 2 + .../store/Workspaces/devWorkspaces/index.ts | 5 ++ .../src/store/__mocks__/storeBuilder.ts | 3 +- 14 files changed, 96 insertions(+), 41 deletions(-) diff --git a/packages/dashboard-backend/src/api/serverConfigApi.ts b/packages/dashboard-backend/src/api/serverConfigApi.ts index 41954cb110..c50a4e3bb5 100644 --- a/packages/dashboard-backend/src/api/serverConfigApi.ts +++ b/packages/dashboard-backend/src/api/serverConfigApi.ts @@ -26,6 +26,7 @@ export function registerServerConfigApi(server: FastifyInstance) { const plugins = serverConfigApi.getDefaultPlugins(cheCustomResource); const editor = serverConfigApi.getDefaultEditor(cheCustomResource); const components = serverConfigApi.getDefaultComponents(cheCustomResource); + const openVSXURL = serverConfigApi.getOpenVSXURL(cheCustomResource); return { defaults: { @@ -33,6 +34,7 @@ export function registerServerConfigApi(server: FastifyInstance) { plugins, components, }, + openVSXURL, }; }); } diff --git a/packages/dashboard-backend/src/devworkspace-client/services/api/serverConfigApi.ts b/packages/dashboard-backend/src/devworkspace-client/services/api/serverConfigApi.ts index bdc2b71327..9e6bea72a2 100644 --- a/packages/dashboard-backend/src/devworkspace-client/services/api/serverConfigApi.ts +++ b/packages/dashboard-backend/src/devworkspace-client/services/api/serverConfigApi.ts @@ -70,6 +70,10 @@ export class ServerConfigApi implements IServerConfigApi { return cheCustomResource.spec.server.workspaceDefaultComponents || []; } + getOpenVSXURL(cheCustomResource: { [key: string]: any }): string | undefined { + return cheCustomResource.spec.components.devWorkspace.cheServer.pluginRegistry.OpenVSXURL; + } + getDashboardWarning(cheCustomResource: { [key: string]: any }): string | undefined { return cheCustomResource.spec.dashboard?.warning; } diff --git a/packages/dashboard-backend/src/devworkspace-client/types/index.ts b/packages/dashboard-backend/src/devworkspace-client/types/index.ts index 621bf54b39..a2751e1ab0 100644 --- a/packages/dashboard-backend/src/devworkspace-client/types/index.ts +++ b/packages/dashboard-backend/src/devworkspace-client/types/index.ts @@ -105,19 +105,23 @@ export interface IServerConfigApi { */ getDefaultComponents(cheCustomResource: { [key: string]: any }): V220DevfileComponents[]; /** - * Returns a maintenance warning + * Returns the openVSX URL if it is defined. + */ + getOpenVSXURL(cheCustomResource: { [key: string]: any }): string | undefined; + /** + * Returns a maintenance warning. */ getDashboardWarning(cheCustomResource: { [key: string]: any }): string | undefined; /** - * Returns limit of running workspaces per user + * Returns limit of running workspaces per user. */ getRunningWorkspacesLimit(cheCustomResource: { [key: string]: any }): number; } export interface IKubeConfigApi { /** - * Inject the kubeconfig into all containers with the given devworkspaceId in a namespace + * Inject the kubeconfig into all containers with the given devworkspaceId in a namespace. */ injectKubeConfig(namespace: string, devworkspaceId: string): Promise; } diff --git a/packages/dashboard-frontend/src/services/bootstrap/index.ts b/packages/dashboard-frontend/src/services/bootstrap/index.ts index 29564f72b3..383065f29e 100644 --- a/packages/dashboard-frontend/src/services/bootstrap/index.ts +++ b/packages/dashboard-frontend/src/services/bootstrap/index.ts @@ -41,6 +41,7 @@ import { AlertVariant } from '@patternfly/react-core'; import SessionStorageService, { SessionStorageKey } from '../session-storage'; import { buildDetailsLocation, buildIdeLoaderLocation } from '../helpers/location'; import { selectAllWorkspaces } from '../../store/Workspaces/selectors'; +import { selectOpenVSXUrl } from '../../store/ServerConfig/selectors'; /** * This class executes a few initial instructions @@ -218,14 +219,16 @@ export default class Bootstrap { selectDwEditorsPluginsList(state.dwPlugins.defaultEditorName)(state).forEach(dwEditor => { pluginsByUrl[dwEditor.url] = dwEditor.devfile; }); - const settings = this.store.getState().workspacesSettings.settings; + const openVSXUrl = selectOpenVSXUrl(state); + const settings = state.workspacesSettings.settings; const pluginRegistryUrl = settings['cheWorkspacePluginRegistryUrl']; const pluginRegistryInternalUrl = settings['cheWorkspacePluginRegistryInternalUrl']; const updates = await this.devWorkspaceClient.checkForTemplatesUpdate( defaultNamespace, pluginsByUrl, - pluginRegistryUrl || '', - pluginRegistryInternalUrl || '', + pluginRegistryUrl, + pluginRegistryInternalUrl, + openVSXUrl, ); if (Object.keys(updates).length > 0) { await this.devWorkspaceClient.updateTemplates(defaultNamespace, updates); diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/serverConfigApi.ts b/packages/dashboard-frontend/src/services/dashboard-backend-client/serverConfigApi.ts index d9803b2461..22e3d1458e 100644 --- a/packages/dashboard-frontend/src/services/dashboard-backend-client/serverConfigApi.ts +++ b/packages/dashboard-frontend/src/services/dashboard-backend-client/serverConfigApi.ts @@ -16,6 +16,15 @@ import { prefix } from './const'; import { api } from '@eclipse-che/common'; import { V220DevfileComponents } from '@devfile/api'; +export interface ServerConfig { + defaults: { + editor: string | undefined; + components: V220DevfileComponents[]; + plugins: api.IWorkspacesDefaultPlugins[]; + }; + openVSXURL: string | undefined; +} + /** * Returns an array of default plug-ins per editor * @@ -23,13 +32,7 @@ import { V220DevfileComponents } from '@devfile/api'; * default plug-ins for the specified editor, * default editor and default components */ -export async function getServerConfig(): Promise<{ - defaults: { - plugins: api.IWorkspacesDefaultPlugins[]; - components: V220DevfileComponents[]; - editor: string | undefined; - }; -}> { +export async function getServerConfig(): Promise { const url = `${prefix}/server-config`; try { const response = await axios.get(url); diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.create.spec.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.create.spec.ts index 4e71a3e85b..0a7831be9b 100644 --- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.create.spec.ts +++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.create.spec.ts @@ -79,6 +79,7 @@ describe('DevWorkspace client, create', () => { undefined, undefined, undefined, + undefined, {}, ); @@ -100,6 +101,7 @@ describe('DevWorkspace client, create', () => { [], undefined, undefined, + undefined, 'eclipse/theia/next', {}, ); @@ -188,6 +190,7 @@ describe('DevWorkspace client, create', () => { undefined, undefined, undefined, + undefined, ); expect(spyCreateWorkspace).toBeCalledWith( @@ -209,6 +212,7 @@ describe('DevWorkspace client, create', () => { undefined, 'http://plugin.registry.url', 'http://internal.plugin.registry.url', + undefined, ); expect(spyCreateWorkspaceTemplate).toBeCalledWith( @@ -243,6 +247,7 @@ describe('DevWorkspace client, create', () => { undefined, undefined, undefined, + undefined, ); expect(spyCreateWorkspaceTemplate).toBeCalledWith( diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.editorUpdate.spec.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.editorUpdate.spec.ts index c65a3f78f5..ad7ca2d42f 100644 --- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.editorUpdate.spec.ts +++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.editorUpdate.spec.ts @@ -48,6 +48,7 @@ describe('DevWorkspace client editor update', () => { }, pluginRegistryUrl, pluginRegistryInternalUrl, + undefined, ); expect(mockPatch.mock.calls).toEqual([ @@ -84,6 +85,7 @@ describe('DevWorkspace client editor update', () => { }, pluginRegistryUrl, pluginRegistryInternalUrl, + undefined, ); expect(mockPatch.mock.calls).toEqual([ @@ -113,6 +115,7 @@ describe('DevWorkspace client editor update', () => { {}, pluginRegistryUrl, pluginRegistryInternalUrl, + undefined, ); expect(mockPatch.mock.calls).toEqual([ @@ -149,6 +152,7 @@ describe('DevWorkspace client editor update', () => { {}, pluginRegistryUrl, pluginRegistryInternalUrl, + undefined, ); expect(mockPatch.mock.calls).toEqual([ diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/devWorkspaceClient.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/devWorkspaceClient.ts index b1869dab44..1b4cadada2 100644 --- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/devWorkspaceClient.ts +++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/devWorkspaceClient.ts @@ -135,6 +135,7 @@ export class DevWorkspaceClient extends WorkspaceClient { private readonly maxStatusAttempts: number; private readonly pluginRegistryUrlEnvName: string; private readonly pluginRegistryInternalUrlEnvName: string; + private readonly openVSXUrlEnvName: string; private readonly dashboardUrlEnvName: string; private readonly websocketClient: WebsocketClient; private webSocketEventEmitter: EventEmitter; @@ -154,6 +155,7 @@ export class DevWorkspaceClient extends WorkspaceClient { this.maxStatusAttempts = 10; this.pluginRegistryUrlEnvName = 'CHE_PLUGIN_REGISTRY_URL'; this.pluginRegistryInternalUrlEnvName = 'CHE_PLUGIN_REGISTRY_INTERNAL_URL'; + this.openVSXUrlEnvName = 'OPENVSX_REGISTRY_URL'; this.dashboardUrlEnvName = 'CHE_DASHBOARD_URL'; this.webSocketEventEmitter = new EventEmitter(); this.webSocketEventName = 'websocketClose'; @@ -252,8 +254,9 @@ export class DevWorkspaceClient extends WorkspaceClient { devworkspace: devfileApi.DevWorkspace, devworkspaceTemplate: devfileApi.DevWorkspaceTemplate, editorId: string | undefined, - pluginRegistryUrl = '', - pluginRegistryInternalUrl = '', + pluginRegistryUrl: string | undefined, + pluginRegistryInternalUrl: string | undefined, + openVSXUrl: string | undefined, ): Promise { // create DW devworkspace.spec.routingClass = 'che'; @@ -274,7 +277,12 @@ export class DevWorkspaceClient extends WorkspaceClient { devworkspace.spec.started = false; const createdWorkspace = await DwApi.createWorkspace(devworkspace); - this.addEnvVarsToContainers(components, pluginRegistryUrl, pluginRegistryInternalUrl); + this.addEnvVarsToContainers( + components, + pluginRegistryUrl, + pluginRegistryInternalUrl, + openVSXUrl, + ); // create DWT devworkspaceTemplate.metadata.namespace = defaultNamespace; @@ -291,6 +299,7 @@ export class DevWorkspaceClient extends WorkspaceClient { devworkspaceTemplate.spec?.components, pluginRegistryUrl, pluginRegistryInternalUrl, + openVSXUrl, ); await DwtApi.createTemplate(devworkspaceTemplate); @@ -315,6 +324,7 @@ export class DevWorkspaceClient extends WorkspaceClient { dwEditorsPlugins: { devfile: devfileApi.Devfile; url: string }[], pluginRegistryUrl: string | undefined, pluginRegistryInternalUrl: string | undefined, + openVSXUrl: string | undefined, editorId: string | undefined, optionalFilesContent: { [fileName: string]: string }, ): Promise { @@ -489,6 +499,7 @@ export class DevWorkspaceClient extends WorkspaceClient { template.spec?.components, pluginRegistryUrl || '', pluginRegistryInternalUrl || '', + openVSXUrl, ); const pluginDWT = await DwtApi.createTemplate(template); @@ -500,6 +511,7 @@ export class DevWorkspaceClient extends WorkspaceClient { createdWorkspace.spec.template.components, pluginRegistryUrl || '', pluginRegistryInternalUrl || '', + openVSXUrl, ); const patch = [ @@ -521,12 +533,14 @@ export class DevWorkspaceClient extends WorkspaceClient { | V1alpha2DevWorkspaceSpecTemplateComponents[] | V1alpha2DevWorkspaceTemplateSpecComponents[] | undefined, - pluginRegistryUrl: string, - pluginRegistryInternalUrl: string, + pluginRegistryUrl: string | undefined, + pluginRegistryInternalUrl: string | undefined, + openVSXUrl: string | undefined, ): void { if (components === undefined) { return; } + const dashboardUrl = window.location.origin; for (const component of components) { const container = component.container; @@ -537,22 +551,33 @@ export class DevWorkspaceClient extends WorkspaceClient { env => env.name !== this.dashboardUrlEnvName && env.name !== this.pluginRegistryUrlEnvName && - env.name !== this.pluginRegistryInternalUrlEnvName, + env.name !== this.pluginRegistryInternalUrlEnvName && + env.name !== this.openVSXUrlEnvName, ); - envs.push( - { + if (dashboardUrl) { + envs.push({ name: this.dashboardUrlEnvName, - value: window.location.origin, - }, - { + value: dashboardUrl, + }); + } + if (pluginRegistryUrl) { + envs.push({ name: this.pluginRegistryUrlEnvName, value: pluginRegistryUrl, - }, - { + }); + } + if (pluginRegistryInternalUrl) { + envs.push({ name: this.pluginRegistryInternalUrlEnvName, value: pluginRegistryInternalUrl, - }, - ); + }); + } + if (openVSXUrl) { + envs.push({ + name: this.openVSXUrlEnvName, + value: openVSXUrl, + }); + } container.env = envs; } } @@ -932,8 +957,9 @@ export class DevWorkspaceClient extends WorkspaceClient { async checkForTemplatesUpdate( namespace: string, pluginsByUrl: { [url: string]: devfileApi.Devfile } = {}, - pluginRegistryUrl = '', - pluginRegistryInternalUrl = '', + pluginRegistryUrl: string | undefined, + pluginRegistryInternalUrl: string | undefined, + openVSXUrl: string | undefined, ): Promise<{ [templateName: string]: api.IPatch[] }> { const templates = await DwtApi.getTemplates(namespace); const managedTemplates = templates.filter( @@ -969,6 +995,7 @@ export class DevWorkspaceClient extends WorkspaceClient { spec.components, pluginRegistryUrl, pluginRegistryInternalUrl, + openVSXUrl, ); } else { spec[key] = plugin[key]; diff --git a/packages/dashboard-frontend/src/store/Plugins/devWorkspacePlugins/__tests__/index.spec.ts b/packages/dashboard-frontend/src/store/Plugins/devWorkspacePlugins/__tests__/index.spec.ts index 983e9d56df..6e301f4e5c 100644 --- a/packages/dashboard-frontend/src/store/Plugins/devWorkspacePlugins/__tests__/index.spec.ts +++ b/packages/dashboard-frontend/src/store/Plugins/devWorkspacePlugins/__tests__/index.spec.ts @@ -317,6 +317,7 @@ describe('dwPlugins store', () => { }, ], }, + openVSXURL: undefined, }) .build() as MockStoreEnhanced< AppState, diff --git a/packages/dashboard-frontend/src/store/ServerConfig/__tests__/index.spec.ts b/packages/dashboard-frontend/src/store/ServerConfig/__tests__/index.spec.ts index dd17026c7b..a18522dec8 100644 --- a/packages/dashboard-frontend/src/store/ServerConfig/__tests__/index.spec.ts +++ b/packages/dashboard-frontend/src/store/ServerConfig/__tests__/index.spec.ts @@ -82,6 +82,7 @@ describe('dwPlugins store', () => { }, ], }, + openVSXURL: undefined, }, }, ]; diff --git a/packages/dashboard-frontend/src/store/ServerConfig/index.ts b/packages/dashboard-frontend/src/store/ServerConfig/index.ts index f7331ef84a..45d55bfa06 100644 --- a/packages/dashboard-frontend/src/store/ServerConfig/index.ts +++ b/packages/dashboard-frontend/src/store/ServerConfig/index.ts @@ -11,19 +11,11 @@ */ import { Action, Reducer } from 'redux'; -import common, { api } from '@eclipse-che/common'; +import common from '@eclipse-che/common'; import { AppThunk } from '../'; import { createObject } from '../helpers'; import * as ServerConfigApi from '../../services/dashboard-backend-client/serverConfigApi'; -import { V220DevfileComponents } from '@devfile/api'; - -export interface ServerConfig { - defaults: { - editor: string | undefined; - components: V220DevfileComponents[]; - plugins: api.IWorkspacesDefaultPlugins[]; - }; -} +import { ServerConfig } from '../../services/dashboard-backend-client/serverConfigApi'; export interface State { isLoading: boolean; @@ -80,6 +72,7 @@ export const actionCreators: ActionCreators = { const unloadedState: State = { isLoading: false, config: { + openVSXURL: undefined, defaults: { editor: undefined, components: [], diff --git a/packages/dashboard-frontend/src/store/ServerConfig/selectors.ts b/packages/dashboard-frontend/src/store/ServerConfig/selectors.ts index eafcc0b428..c72942d331 100644 --- a/packages/dashboard-frontend/src/store/ServerConfig/selectors.ts +++ b/packages/dashboard-frontend/src/store/ServerConfig/selectors.ts @@ -26,4 +26,6 @@ export const selectDefaultPlugins = createSelector( state => state.config.defaults?.plugins || [], ); +export const selectOpenVSXUrl = createSelector(selectState, state => state.config.openVSXURL); + export const selectServerConfigError = createSelector(selectState, state => state.error); diff --git a/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts b/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts index ae721f7692..a47b698f90 100644 --- a/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts +++ b/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts @@ -39,6 +39,7 @@ import { injectKubeConfig } from '../../../services/dashboard-backend-client/dev import { selectRunningWorkspacesLimit } from '../../ClusterConfig/selectors'; import { cloneDeep } from 'lodash'; import { delay } from '../../../services/helpers/delay'; +import { selectOpenVSXUrl } from '../../ServerConfig/selectors'; const devWorkspaceClient = container.get(DevWorkspaceClient); @@ -504,6 +505,7 @@ export const actionCreators: ActionCreators = { async (dispatch, getState): Promise => { const state = getState(); const defaultKubernetesNamespace = selectDefaultNamespace(state); + const openVSXUrl = selectOpenVSXUrl(state); const defaultNamespace = defaultKubernetesNamespace.name; try { const cheEditor = editorId ? editorId : state.dwPlugins.defaultEditorName; @@ -518,6 +520,7 @@ export const actionCreators: ActionCreators = { cheEditor, pluginRegistryUrl, pluginRegistryInternalUrl, + openVSXUrl, ); if (workspace.spec.started) { @@ -588,6 +591,7 @@ export const actionCreators: ActionCreators = { // If the devworkspace doesn't have a namespace then we assign it to the default kubernetesNamespace const devWorkspaceDevfile = devfile as devfileApi.Devfile; const defaultNamespace = selectDefaultNamespace(state); + const openVSXURL = selectOpenVSXUrl(state); const dwEditorsList = selectDwEditorsPluginsList(cheEditor)(state); const workspace = await devWorkspaceClient.createFromDevfile( devWorkspaceDevfile, @@ -595,6 +599,7 @@ export const actionCreators: ActionCreators = { dwEditorsList, pluginRegistryUrl, pluginRegistryInternalUrl, + openVSXURL, cheEditor, optionalFilesContent, ); diff --git a/packages/dashboard-frontend/src/store/__mocks__/storeBuilder.ts b/packages/dashboard-frontend/src/store/__mocks__/storeBuilder.ts index 9da72007c8..dd075f1994 100644 --- a/packages/dashboard-frontend/src/store/__mocks__/storeBuilder.ts +++ b/packages/dashboard-frontend/src/store/__mocks__/storeBuilder.ts @@ -27,7 +27,7 @@ import mockThunk from './thunk'; import devfileApi from '../../services/devfileApi'; import { ClusterConfig, ClusterInfo } from '@eclipse-che/common'; import { WorkspacesLogs } from '../../services/helpers/types'; -import { ServerConfig } from '../ServerConfig'; +import { ServerConfig } from '../../services/dashboard-backend-client/serverConfigApi'; export class FakeStoreBuilder { private state: AppState = { @@ -48,6 +48,7 @@ export class FakeStoreBuilder { components: [], plugins: [], }, + openVSXURL: undefined, } as ServerConfig, }, clusterInfo: {