From bd429a0c036aa48feb729769dc3ac9b36a1a3370 Mon Sep 17 00:00:00 2001 From: Vitaliy Gulyy Date: Thu, 14 Nov 2019 17:47:41 +0200 Subject: [PATCH] Use dashboard to restart the workspace (#15180) * Use dashboard to restart the workspace Signed-off-by: Vitaliy Gulyy * Use authorization header instead of query parameter Signed-off-by: Vitaliy Gulyy --- src/app/ide/ide-iframe/ide-iframe.service.ts | 128 ++++++++++++++---- src/app/ide/ide.service.ts | 11 ++ .../api/workspace/che-workspace.factory.ts | 28 ++++ 3 files changed, 143 insertions(+), 24 deletions(-) diff --git a/src/app/ide/ide-iframe/ide-iframe.service.ts b/src/app/ide/ide-iframe/ide-iframe.service.ts index c6fab9e99..382732143 100644 --- a/src/app/ide/ide-iframe/ide-iframe.service.ts +++ b/src/app/ide/ide-iframe/ide-iframe.service.ts @@ -10,7 +10,9 @@ * Red Hat, Inc. - initial API and implementation */ 'use strict'; -import {CheUIElementsInjectorService} from '../../../components/service/injector/che-ui-elements-injector.service'; + +import { CheWorkspace } from '../../../components/api/workspace/che-workspace.factory'; +import IdeSvc from '../ide.service'; /*global $:false */ @@ -26,9 +28,14 @@ interface IIdeIFrameRootScope extends ng.IRootScopeService { * @author Florent Benoit */ class IdeIFrameSvc { - static $inject = ['$window', '$location', '$rootScope', '$mdSidenav']; + + static $inject = ['$window', '$location', '$rootScope', '$mdSidenav', 'cheWorkspace', 'ideSvc']; private $location: ng.ILocationService; + private $rootScope: IIdeIFrameRootScope; + private $mdSidenav: ng.material.ISidenavService; + private cheWorkspace: CheWorkspace; + private ideSvc: IdeSvc; /** * Default constructor that is using resource @@ -36,36 +43,108 @@ class IdeIFrameSvc { constructor($window: ng.IWindowService, $location: ng.ILocationService, $rootScope: IIdeIFrameRootScope, - $mdSidenav: ng.material.ISidenavService) { + $mdSidenav: ng.material.ISidenavService, + cheWorkspace: CheWorkspace, + ideSvc: IdeSvc) { this.$location = $location; + this.$rootScope = $rootScope; + this.$mdSidenav = $mdSidenav; + this.cheWorkspace = cheWorkspace; + this.ideSvc = ideSvc; $window.addEventListener('message', (event: any) => { - if ('show-ide' === event.data) { - if (this.isWaitingIDE()) { - $rootScope.$apply(() => { - $rootScope.showIDE = true; - $rootScope.hideLoader = true; - }); - } - } else if ('show-workspaces' === event.data) { - $rootScope.$apply(() => { - $location.path('/workspaces'); - }); - - } else if ('show-navbar' === event.data) { - $rootScope.hideNavbar = false; - $mdSidenav('left').open(); - - } else if ('hide-navbar' === event.data) { - if (this.isWaitingIDE()) { - $rootScope.hideNavbar = true; - $mdSidenav('left').close(); - } + if (!event || typeof event.data !== "string") { + return; + } + + const msg: string = event.data; + + if ('show-ide' === msg) { + this.showIDE(); + return; + } + + if ('show-workspaces' === msg) { + this.showWorkspaces(); + return; + } + + if ('show-navbar' === msg) { + this.showNavBar(); + return; + } + + if ('hide-navbar' === msg) { + this.hideNavBar(); + return; + } + + if (msg.startsWith('restart-workspace:')) { + this.restartWorkspace(msg); + return; } }, false); } + private showIDE(): void { + if (this.isWaitingIDE()) { + this.$rootScope.$apply(() => { + this.$rootScope.showIDE = true; + this.$rootScope.hideLoader = true; + }); + } + } + + private showWorkspaces(): void { + this.$rootScope.$apply(() => { + this.$location.path('/workspaces'); + }); + } + + private showNavBar(): void { + this.$rootScope.hideNavbar = false; + this.$mdSidenav('left').open(); + } + + private hideNavBar(): void { + if (this.isWaitingIDE()) { + this.$rootScope.hideNavbar = true; + this.$mdSidenav('left').close(); + } + } + + /** + * Restarts the workspace + * + * @param message message from Editor in format + * restart-workspace:${workspaceId}:${token} + * Where + * 'restart-workspace' - action name + * ${workspaceId} - workpsace ID + * ${token} - Che machine token to validate + */ + private restartWorkspace(message: string): void { + // cut action name + message = message.substring(message.indexOf(':') + 1); + + // get workpsace ID + const workspaceId = message.substring(0, message.indexOf(':')); + + // get Che machine token + const token = message.substring(message.indexOf(':') + 1); + + this.cheWorkspace.validateMachineToken(workspaceId, token).then(() => { + this.cheWorkspace.stopWorkspace(workspaceId).then(() => { + this.ideSvc.reloadIdeFrame(); + }).catch((error) => { + console.error('Unable to stop workspace. ', error); + }); + }).catch(() => { + console.error('Unable to stop workspace: token is not valid.'); + }); + } + /** * Returns true if the user is waiting for IDE. * @returns {boolean} @@ -73,6 +152,7 @@ class IdeIFrameSvc { private isWaitingIDE(): boolean { return /\/ide\//.test(this.$location.path()); } + } export default IdeIFrameSvc; diff --git a/src/app/ide/ide.service.ts b/src/app/ide/ide.service.ts index 48b1882d1..46857e5fa 100644 --- a/src/app/ide/ide.service.ts +++ b/src/app/ide/ide.service.ts @@ -194,6 +194,17 @@ class IdeSvc { }); } + /** + * Reloads frame with IDE + */ + reloadIdeFrame(): void { + let iframe = angular.element('#ide-application-iframe'); + if (iframe) { + const src = iframe.attr('src'); + iframe.attr('src', src); + } + } + /** * Emit event to move workspace immediately * to top of the recent workspaces list diff --git a/src/components/api/workspace/che-workspace.factory.ts b/src/components/api/workspace/che-workspace.factory.ts index cd5b78cdd..cd42c5b41 100644 --- a/src/components/api/workspace/che-workspace.factory.ts +++ b/src/components/api/workspace/che-workspace.factory.ts @@ -407,6 +407,34 @@ export class CheWorkspace { return defer.promise; } + /** + * Validates machine token for the workspace + * + * @param workspaceId workspace ID + * @param token Che machine token + */ + validateMachineToken(workspaceId: string, token: string): ng.IPromise { + const defer = this.$q.defer(); + + const promise: ng.IHttpPromise = this.$http.get(`/api/workspace/${workspaceId}`, { + headers: { + 'Authorization': `Bearer ${token}` + } + }); + + promise.then((response: ng.IHttpPromiseCallbackArg) => { + defer.resolve(); + }, (error: any) => { + if (error && error.status === 304) { + defer.resolve(); + return; + } + defer.reject(error); + }); + + return defer.promise; + } + /** * Adds a project on the workspace * @param workspaceId {string} the workspace ID required to add a project