diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000000000000000000000000000000000..7a9dfa044d022f5ca8cf9191e37fef926dd67f77 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "pwa-chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/src/app/computesite.ts b/src/app/computesite.ts index aa2715fccc61c16380666978016bde0d432684cb..1ad0c3dc2c971ed9b5e75c4ebd2ab250a82135b2 100644 --- a/src/app/computesite.ts +++ b/src/app/computesite.ts @@ -12,7 +12,7 @@ export class Computesite { cafingerprint: string; // Certificates contain a CA fingerprint. We use this // to figure out which compute site a certificate is valid // for - appCatalog: BehaviorSubject<Strudelapp[]>; + appCatalogUri: string; appCatalogCmd: string; internalfirewall: boolean; // Does a firewall exist within the site necessitating an extra level of ssh tunnel @@ -23,18 +23,6 @@ export class Computesite { contact: string; } -export class Strudelapp { - url: string; // A url used to retrieve extra config options. May be null - name: string; // Human readable name - startscript: string; // batch script ... should NOT include resource directives - // resource directives like #SBATCH belong in the batchinterface - paramscmd: string; // command to return extra data such as passwords and tokens - // values returned here can be used in the client strings - client: {cmd: string[], redir: string}; - localbind: boolean; // does the application bind to a port on the localhost - // interface or on all interfaces. This behaviour determins - /// how we create tunnels -} export class Health { stat: string; diff --git a/src/app/computesites.service.ts b/src/app/computesites.service.ts index 42b049926055d3dcf7bb3e3088e258d0c440a0f3..8ef1ab93ad2017fab06a90655024a291eff5c584 100644 --- a/src/app/computesites.service.ts +++ b/src/app/computesites.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@angular/core'; -import { Computesite, Strudelapp } from './computesite'; +import { Computesite } from './computesite'; +import { Strudelapp } from './strudelapp'; import {BehaviorSubject, of, combineLatest} from 'rxjs'; import { HttpClientModule, HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; @@ -46,7 +47,7 @@ export class ComputesitesService { let options = { headers: headers, withCredentials: false}; if (s.appCatalogUri !== null) { this.http.get<Strudelapp[]>(s.appCatalogUri,options) - .pipe(catchError(this.handleError('getStrudelApps'))) + .pipe(catchError(this.handleError(' s'))) .subscribe(resp => this.updateStrudelApps(s,resp)); } } @@ -64,7 +65,7 @@ export class ComputesitesService { if (ids != undefined && ids != null) { for (let id of ids) { this.getStrudelAppsIdentity(id) - .subscribe(resp => this.updateStrudelApps(id.site,resp)); + .subscribe(resp => this.updateStrudelApps(id,resp)); } } } @@ -81,9 +82,12 @@ export class ComputesitesService { } private getStrudelAppsCmd(identity: Identity): Observable<Strudelapp[]> { + console.log('running getStrudleAppsCmd',identity) if (identity.site.appCatalogCmd != null) { return (this.tesService.runCommand(identity,identity.site.appCatalogCmd) as Observable<Strudelapp[]>) - .pipe(catchError(this.handleError('getStrudelApps', <Strudelapp[]>[]))) + .pipe( + tap((v) => console.log('getapps',identity,' returned',v)), + catchError(this.handleError('getStrudelApps', <Strudelapp[]>[]))) } return of([] as Strudelapp[]) } @@ -107,18 +111,18 @@ export class ComputesitesService { } - updateStrudelApps(site: Computesite, apps) { + updateStrudelApps(id: Identity, apps) { var sapps: Strudelapp[]; var localapps: Strudelapp[]; sapps = <Strudelapp[]>apps; - localapps = JSON.parse(localStorage.getItem(site.name+'-apps')) + localapps = JSON.parse(localStorage.getItem(id.site.name+'-apps')) if (localapps !== null) { for (let a of localapps) { sapps.push(a); } } - site.appCatalog.next(sapps); + id.appCatalog.next(sapps); } private handleError<T> (operation = 'operation', result?: T) { @@ -160,13 +164,11 @@ export class ComputesitesService { } if (localcomputesites !== null ) { for (let cs of localcomputesites) { - cs.appCatalog = new BehaviorSubject<Strudelapp[]>([]); computesites.push(cs); } } for (let cs of resp) { let computesite = <Computesite>cs; - computesite.appCatalog = new BehaviorSubject<Strudelapp[]>([]) computesites.push(computesite); } this.computesites.next(computesites); diff --git a/src/app/identity.ts b/src/app/identity.ts index ac8610079b5f224d3e3b00c2447eb178228eca8b..a332f822790418ba53e62282224fa455e1d12e72 100644 --- a/src/app/identity.ts +++ b/src/app/identity.ts @@ -1,6 +1,7 @@ import {Computesite, Health} from './computesite'; import {Job} from './job'; import {BehaviorSubject} from 'rxjs'; +import {Strudelapp} from './strudelapp'; // Identities are defined by a username on a computer, but rather than just // DNS entry, there is extra info in the Computesite export class Identity { @@ -13,6 +14,7 @@ export class Identity { joblist: BehaviorSubject<Job[]>; quotas: any[]; expiry: number; + appCatalog: BehaviorSubject<Strudelapp[]>; constructor( username: string, site: Computesite, expiry: number) { this.username = username; this.site = site; @@ -20,8 +22,10 @@ export class Identity { this.systemalerts = new BehaviorSubject<Health[]>(null); this.accountalerts = new BehaviorSubject<Health[]>(null); this.joblist = new BehaviorSubject<Job[]>([]); + this.appCatalog = new BehaviorSubject<Strudelapp[]>([]); this.quotas = []; this.expiry = expiry; + } copy_skip_catalog(): Identity { diff --git a/src/app/joblist/joblist.component.ts b/src/app/joblist/joblist.component.ts index e336904dbfc282aba3d18af23aa060dc649e3a0f..7aa175c87108bf736664418106bc246a7ef1f118 100644 --- a/src/app/joblist/joblist.component.ts +++ b/src/app/joblist/joblist.component.ts @@ -92,7 +92,7 @@ export class JoblistComponent implements OnInit { // any jobs in the joblist that we don't know which application they arem try to figure it out for (j of joblist) { if (j.app === undefined || j.app == null) { - j.app = Strudelapp.getApp(j.appname,identity.site.appCatalog.value); + j.app = Strudelapp.getApp(j.appname,identity.appCatalog.value); } if (j.identity == undefined) { j.identity = identity; diff --git a/src/app/jobs.service.ts b/src/app/jobs.service.ts index b244cacc0a2b96da636675baf14ce394ffa5df7c..a20b8026dcda9bb537d54604a08b6004dc19617c 100644 --- a/src/app/jobs.service.ts +++ b/src/app/jobs.service.ts @@ -45,13 +45,15 @@ export class JobsService { if (error.hasOwnProperty("error") && error.error.hasOwnProperty("message")) { if (error.error.message.indexOf("Permission denied") != -1) { this.notifications.notify("Your login appears to have expired. Please log in again"); - this.authService.updateAgentContents().subscribe((_) => {return}); + //this.authService.updateAgentContents().subscribe((_) => {return}); return; } + this.notifications.notify("Unable to retrieve a list of running jobs.\nDid your session expire?\nThe error messge was " + error.error.message); + return; } - this.notifications.notify("Unable to retrieve a list of running jobs.\nDid your session expire?") console.error(error); - this.authService.updateAgentContents().subscribe((_) => {return}); + this.notifications.notify("Unable to retrieve a list of running jobs.\nDid your session expire?"); + //this.authService.updateAgentContents().subscribe((_) => {return}); } } diff --git a/src/app/launcher/launcher.component.html b/src/app/launcher/launcher.component.html index d71b9a883ee9b4462ed73326ff6ff6cc6b6d47a9..1211c94bf54b6f49ba2a15f148533fd5dd8b9a55 100644 --- a/src/app/launcher/launcher.component.html +++ b/src/app/launcher/launcher.component.html @@ -37,7 +37,7 @@ </button> </mat-list-item> - <app-strudelapplist [applist]=id.site.appCatalog [identity]="id" (appChange)="selectApp($event)" style="width: 100%"></app-strudelapplist> + <app-strudelapplist [applist]=id.appCatalog [identity]="id" (appChange)="selectApp($event)" style="width: 100%"></app-strudelapplist> </mat-list> </mat-expansion-panel> <!--<div style="width: 100%; border-bottom: 1px solid var(--panel-border-color);"></div>--> diff --git a/src/app/launcher/launcher.component.ts b/src/app/launcher/launcher.component.ts index f9770a80c20f98a1b569929e539dea129ab1b17d..f5d037fd3f7af591c8e7dea4e04ad387cdb06b39 100644 --- a/src/app/launcher/launcher.component.ts +++ b/src/app/launcher/launcher.component.ts @@ -233,8 +233,8 @@ export class LauncherComponent implements OnInit { if (apps === null) { apps = 'accountinfo'; } - if (id.site.appCatalog.value === undefined || id.site.appCatalog.value === null || (id.site.appCatalog.value).length == 0) { - id.site.appCatalog.pipe(filter((v) => v !== null && v.length > 0),take(1)).subscribe(() => this.updateIdApp(params,appidentities)); + if (id.appCatalog.value === undefined || id.appCatalog.value === null || (id.appCatalog.value).length == 0) { + id.appCatalog.pipe(filter((v) => v !== null && v.length > 0),take(1)).subscribe(() => this.updateIdApp(params,appidentities)); return } var app: Strudelapp = this.getApp(id,apps); @@ -247,7 +247,7 @@ export class LauncherComponent implements OnInit { if (id == 'accountinfo') { return null; } - return Strudelapp.getApp(v,id.site.appCatalog.value); + return Strudelapp.getApp(v,id.appCatalog.value); } getId(v: any, appidentities: Identity[]) { diff --git a/src/app/tes.service.ts b/src/app/tes.service.ts index 9d5857b1390cc56a577e9dacf919a72c82728860..4aaaef5f6a34b1fefa54d6cc8197c0bb7cb2a8d1 100644 --- a/src/app/tes.service.ts +++ b/src/app/tes.service.ts @@ -54,7 +54,6 @@ public openWindow$: Subject<any>; private buildParams(app: Strudelapp, identity: Identity, batchinterface: BatchInterface, appinst?: any): string { let params = new URLSearchParams(); let id = identity.copy_skip_catalog(); - id.site.appCatalog = null; if (appinst!== null) { params.set('appinstance',JSON.stringify(appinst)); } diff --git a/src/assets/config/m3apps.test.json b/src/assets/config/m3apps.test.json index b12b6fa77e46aa3a9c0db500aeac691da2da22a3..bcac520e069c97b25134fa3a13e169333b4718d3 100644 --- a/src/assets/config/m3apps.test.json +++ b/src/assets/config/m3apps.test.json @@ -43,7 +43,7 @@ "instactions": [ { "name": "Connect", - "paramscmd": "/usr/local/sv2/jupyter/jupyter_params.sh {jobid}", + "paramscmd": "/usr/local/sv2/jupyter/jupyter_params.py {jobid}", "client": {"cmd": null, "redir": "?token={token}"}, "states": ["RUNNING"] },