From ffd7a33f2a9c70b03a5bcbe0d2dabd10164f08a0 Mon Sep 17 00:00:00 2001 From: Oleksii Orel Date: Thu, 10 Oct 2019 08:57:04 +0300 Subject: [PATCH] Fix load factory flow in the case with policies.create=peruser Signed-off-by: Oleksii Orel --- .../load-factory/load-factory.controller.ts | 120 ++++++++++++------ .../factories/load-factory/load-factory.html | 4 +- .../create-workspace.controller.ts | 5 +- .../create-workspace/create-workspace.html | 3 +- .../devfile-selector.controller.ts | 2 + .../devfile-selector.directive.ts | 2 +- .../list-workspaces/list-workspaces.html | 6 +- .../workspace-item.controller.ts | 21 +++ .../workspace-item/workspace-item.html | 16 ++- dashboard/src/components/typings/che.d.ts | 3 + 10 files changed, 130 insertions(+), 52 deletions(-) diff --git a/dashboard/src/app/factories/load-factory/load-factory.controller.ts b/dashboard/src/app/factories/load-factory/load-factory.controller.ts index bb4a934db84..e278933e86b 100644 --- a/dashboard/src/app/factories/load-factory/load-factory.controller.ts +++ b/dashboard/src/app/factories/load-factory/load-factory.controller.ts @@ -11,13 +11,16 @@ */ 'use strict'; import {CheAPI} from '../../../components/api/che-api.factory'; -import {CheWorkspace} from '../../../components/api/workspace/che-workspace.factory'; +import {CheWorkspace, WorkspaceStatus} from '../../../components/api/workspace/che-workspace.factory'; import {LoadFactoryService, FactoryLoadingStep} from './load-factory.service'; import {CheNotification} from '../../../components/notification/che-notification.factory'; import {RouteHistory} from '../../../components/routing/route-history.service'; import {CheJsonRpcApi} from '../../../components/api/json-rpc/che-json-rpc-api.factory'; import {CheJsonRpcMasterApi} from '../../../components/api/json-rpc/che-json-rpc-master-api'; +const STARTING = WorkspaceStatus[WorkspaceStatus.STARTING]; +const RUNNING = WorkspaceStatus[WorkspaceStatus.RUNNING]; + const WS_AGENT_STEP: number = 4; /** @@ -29,7 +32,7 @@ export class LoadFactoryController { static $inject = ['cheAPI', 'cheWorkspace','cheJsonRpcApi', '$route', '$timeout', '$mdDialog', 'loadFactoryService', 'lodash', 'cheNotification', '$location', 'routeHistory', '$window', 'loadFactoryService']; private cheAPI: CheAPI; - cheWorkspace: CheWorkspace; + private cheWorkspace: CheWorkspace; private $timeout: ng.ITimeoutService; private $mdDialog: ng.material.IDialogService; private loadFactoryService: LoadFactoryService; @@ -242,9 +245,34 @@ export class LoadFactoryController { case 'peruser' : workspace = this.lodash.find(this.workspaces, (w: che.IWorkspace) => { if (this.factory.id) { - return this.factory.id === (w.attributes as any).factoryId; - } else if (this.routeParams.url){ - return this.routeParams.url === (w.attributes as any).factoryurl; + return this.factory.id === w.attributes.factoryId; + } else if (this.routeParams.url) { + const factoryUrl = w.attributes.factoryurl; + // compare factory URL and route params + if (angular.isDefined(factoryUrl)) { + const factoryUrlObj = new (window as any).URL(factoryUrl); + const isPathCorrect = `${factoryUrlObj.origin}${factoryUrlObj.pathname}` === this.routeParams.url; + if (isPathCorrect === false) { + return false; + } + + let factoryUrlParamsNumber = 0; + let hasExtraKey = false; + for (const [key, value] of factoryUrlObj.searchParams) { + if (hasExtraKey) { + return false; + } + factoryUrlParamsNumber++; + hasExtraKey = this.routeParams[key] !== value; + } + if (hasExtraKey) { + return false; + } + + // `routeParams` contains the `url` param which is not in `factoryUrl` + const paramsNumber = Object.keys(this.routeParams).length - 1; + return factoryUrlParamsNumber === paramsNumber; + } } return false; }); @@ -296,8 +324,18 @@ export class LoadFactoryController { creationPromise = this.cheAPI.getWorkspace().createWorkspaceFromConfig(null, config, attrs); } else if (this.factory.devfile) { let devfile = this.factory.devfile; - // set devfile attribute: - let attrs = {factoryurl: this.routeParams.url}; + // set devfile attributes + let url = ''; + let params = ''; + for (const key in this.routeParams) { + if (key === 'url') { + url = this.routeParams[key]; + } else { + params += `${!params ? '?' : '&'}${key}=${this.routeParams[key]}`; + } + } + + const attrs = {factoryurl: `${url}${params}`}; creationPromise = this.cheAPI.getWorkspace().createWorkspaceFromDevfile(null, devfile, attrs); } creationPromise.then((data: any) => { @@ -342,10 +380,14 @@ export class LoadFactoryController { startWorkspace(workspace: che.IWorkspace): void { this.workspace = workspace; - if (workspace.status === 'RUNNING') { - this.loadFactoryService.setCurrentProgressStep(4); - this.importProjects(); - return; + if (workspace.status === RUNNING) { + if(workspace.config && workspace.config.projects) { + this.loadFactoryService.setCurrentProgressStep(4); + this.importProjects(); + } else { + this.finish(); + } + return; } this.subscribeOnEvents(workspace); @@ -361,31 +403,34 @@ export class LoadFactoryController { * @param workspace */ doStartWorkspace(workspace: che.IWorkspace): void { - let startWorkspacePromise = this.cheAPI.getWorkspace().startWorkspace(workspace.id); - this.loadFactoryService.goToNextStep(); + this.cheAPI.getWorkspace().fetchWorkspaceDetails(workspace.id).then(() => { + const workspaceStatus = this.cheAPI.getWorkspace().getWorkspacesById().get(workspace.id).status; + if ((workspaceStatus !== RUNNING) && (workspaceStatus !== STARTING)) { + this.cheAPI.getWorkspace().startWorkspace(workspace.id).then((data: any) => { + console.log('Workspace started', data); + }, (error: any) => { + let errorMessage; + + if (!error || !error.data) { + errorMessage = 'This factory is unable to start a new workspace.'; + } else if (error.data.errorCode === 10000 && error.data.attributes) { + let attributes = error.data.attributes; + + errorMessage = 'This factory is unable to start a new workspace.' + + ' Your running workspaces are consuming ' + + attributes.used_ram + attributes.ram_unit + ' RAM.' + + ' Your current RAM limit is ' + attributes.limit_ram + attributes.ram_unit + + '. This factory requested an additional ' + + attributes.required_ram + attributes.ram_unit + '.' + + ' You can stop other workspaces to free resources.'; + } else { + errorMessage = error.data.message; + } - startWorkspacePromise.then((data: any) => { - console.log('Workspace started', data); - }, (error: any) => { - let errorMessage; - - if (!error || !error.data) { - errorMessage = 'This factory is unable to start a new workspace.'; - } else if (error.data.errorCode === 10000 && error.data.attributes) { - let attributes = error.data.attributes; - - errorMessage = 'This factory is unable to start a new workspace.' + - ' Your running workspaces are consuming ' + - attributes.used_ram + attributes.ram_unit + ' RAM.' + - ' Your current RAM limit is ' + attributes.limit_ram + attributes.ram_unit + - '. This factory requested an additional ' + - attributes.required_ram + attributes.ram_unit + '.' + - ' You can stop other workspaces to free resources.'; - } else { - errorMessage = error.data.message; + this.handleError({data: {message: errorMessage}}); + }); } - - this.handleError({data: {message: errorMessage}}); + this.loadFactoryService.goToNextStep(); }); } @@ -422,7 +467,6 @@ export class LoadFactoryController { this.jsonRpcMasterApi.subscribeEnvironmentStatus(workspaceId, environmentStatusHandler); let environmentOutputHandler = (message: any) => { - // skip displaying machine logs after workspace agent: if (this.loadFactoryService.getCurrentProgressStep() === WS_AGENT_STEP) { return; } @@ -449,7 +493,7 @@ export class LoadFactoryController { this.getLoadingSteps()[this.getCurrentProgressStep()].hasError = true; } - if (message.status === 'RUNNING' && message.workspaceId === workspaceId) { + if (message.status === RUNNING && message.workspaceId === workspaceId) { this.finish(); } }; @@ -597,8 +641,8 @@ export class LoadFactoryController { // people should go back to the dashboard after factory is initialized this.routeHistory.pushPath('/'); - var ideParams = []; - if (this.routeParams) { + const ideParams = []; + if (this.routeParams && this.workspace.devfile) { if (this.routeParams.id || (this.routeParams.name && this.routeParams.user)) { ideParams.push('factory-id:' + this.factory.id); } else { diff --git a/dashboard/src/app/factories/load-factory/load-factory.html b/dashboard/src/app/factories/load-factory/load-factory.html index 537b1ecdae3..b40bf422bd9 100644 --- a/dashboard/src/app/factories/load-factory/load-factory.html +++ b/dashboard/src/app/factories/load-factory/load-factory.html @@ -32,8 +32,8 @@ - - This factory is using old workspace definition format which is not compatible anymore. + + This factory is using old workspace definition format which is not compatible anymore. Please follow the documentation to update the definition of the workspace and benefits from the latest capabilities. diff --git a/dashboard/src/app/workspaces/create-workspace/create-workspace.controller.ts b/dashboard/src/app/workspaces/create-workspace/create-workspace.controller.ts index 3647847fb05..d7449e01450 100644 --- a/dashboard/src/app/workspaces/create-workspace/create-workspace.controller.ts +++ b/dashboard/src/app/workspaces/create-workspace/create-workspace.controller.ts @@ -102,6 +102,9 @@ export class CreateWorkspaceController { * Hide progress loader if true. */ private hideLoader: boolean; + + private stackName: string; + /** * Default constructor that is using resource injection */ @@ -304,7 +307,7 @@ export class CreateWorkspaceController { // update workspace name let devfileSource = angular.copy(this.selectedDevfile); devfileSource.metadata.name = this.workspaceName; - return this.createWorkspaceSvc.createWorkspaceFromDevfile(devfileSource, null); + return this.createWorkspaceSvc.createWorkspaceFromDevfile(devfileSource, {stackName: this.stackName}); } /** diff --git a/dashboard/src/app/workspaces/create-workspace/create-workspace.html b/dashboard/src/app/workspaces/create-workspace/create-workspace.html index 23b9d199917..51730a0aa5d 100644 --- a/dashboard/src/app/workspaces/create-workspace/create-workspace.html +++ b/dashboard/src/app/workspaces/create-workspace/create-workspace.html @@ -53,7 +53,8 @@ - + diff --git a/dashboard/src/app/workspaces/create-workspace/devfile-selector/devfile-selector.controller.ts b/dashboard/src/app/workspaces/create-workspace/devfile-selector/devfile-selector.controller.ts index a1703e40ee8..afbee6bf186 100644 --- a/dashboard/src/app/workspaces/create-workspace/devfile-selector/devfile-selector.controller.ts +++ b/dashboard/src/app/workspaces/create-workspace/devfile-selector/devfile-selector.controller.ts @@ -27,6 +27,7 @@ export class DevfileSelectorController { devfileOrderBy: string; onDevfileSelect: Function; selectedDevfile: any; + stackName: string; /** * Default constructor that is using resource injection @@ -54,6 +55,7 @@ export class DevfileSelectorController { devfileOnClick(devfile: any): void { this.selectedDevfile = devfile; + this.stackName = devfile.displayName; let location = this.cheWorkspace.getWorkspaceSettings().cheWorkspaceDevfileRegistryUrl; diff --git a/dashboard/src/app/workspaces/create-workspace/devfile-selector/devfile-selector.directive.ts b/dashboard/src/app/workspaces/create-workspace/devfile-selector/devfile-selector.directive.ts index 2feb4beba35..6db26e7c91e 100644 --- a/dashboard/src/app/workspaces/create-workspace/devfile-selector/devfile-selector.directive.ts +++ b/dashboard/src/app/workspaces/create-workspace/devfile-selector/devfile-selector.directive.ts @@ -35,7 +35,7 @@ export class DevfileSelector implements ng.IDirective { */ constructor() { this.scope = { - devfileIdSelected: '=', + stackName: '=', onDevfileSelect: '&' }; } diff --git a/dashboard/src/app/workspaces/list-workspaces/list-workspaces.html b/dashboard/src/app/workspaces/list-workspaces/list-workspaces.html index a46a43db6eb..4a76039c070 100644 --- a/dashboard/src/app/workspaces/list-workspaces/list-workspaces.html +++ b/dashboard/src/app/workspaces/list-workspaces/list-workspaces.html @@ -50,15 +50,15 @@ che-sort-value="listWorkspacesCtrl.workspaceOrderBy" che-sort-item="config.name" che-column-title="Name"> - - - diff --git a/dashboard/src/app/workspaces/list-workspaces/workspace-item/workspace-item.controller.ts b/dashboard/src/app/workspaces/list-workspaces/workspace-item/workspace-item.controller.ts index a19c8242567..951777c8af3 100644 --- a/dashboard/src/app/workspaces/list-workspaces/workspace-item/workspace-item.controller.ts +++ b/dashboard/src/app/workspaces/list-workspaces/workspace-item/workspace-item.controller.ts @@ -71,6 +71,27 @@ export class WorkspaceItemCtrl { this.workspaceName = this.cheWorkspace.getWorkspaceDataManager().getName(this.workspace); } + get stackDescription(): string { + const attributes = this.workspace.attributes; + let description = attributes.stackId ? attributes.stackId : attributes.stackName; + if (!description) { + description = attributes.factoryId ? attributes.factoryId : attributes.factoryurl; + } + return description; + } + + /** + * Returns workspace projects. + * + * @returns {Array} + */ + get projects(): Array { + if (this.workspace.devfile) { + return this.workspace.devfile.projects || []; + } + return this.workspace.config.projects || []; + } + /** * Returns `true` if supported. * diff --git a/dashboard/src/app/workspaces/list-workspaces/workspace-item/workspace-item.html b/dashboard/src/app/workspaces/list-workspaces/workspace-item/workspace-item.html index 3120d0055ee..a543a2cbbb3 100644 --- a/dashboard/src/app/workspaces/list-workspaces/workspace-item/workspace-item.html +++ b/dashboard/src/app/workspaces/list-workspaces/workspace-item/workspace-item.html @@ -52,7 +52,7 @@ -
RAM @@ -60,20 +60,24 @@
-
Projects - {{workspaceItemCtrl.workspace.config.projects.length}} - projects + + {{workspaceItemCtrl.projects.length > 0 ? workspaceItemCtrl.projects.length : '-'}} + + projects + +
-
Stack - {{workspaceItemCtrl.workspace.attributes.stackId}} + {{workspaceItemCtrl.stackDescription}}
diff --git a/dashboard/src/components/typings/che.d.ts b/dashboard/src/components/typings/che.d.ts index ff1996cff9d..e0aa5088550 100755 --- a/dashboard/src/components/typings/che.d.ts +++ b/dashboard/src/components/typings/che.d.ts @@ -313,6 +313,9 @@ declare namespace che { created: number; updated?: number; stackId?: string; + stackName?: string; + factoryId?: string; + factoryurl?: string; errorMessage?: string; [propName: string]: string | number; }