Commit cf4e5552 authored by Chris Hines's avatar Chris Hines
Browse files

if stat fails, display the error instead of immediately refreshing...

if stat fails, display the error instead of immediately refreshing #156
parent 7e8ae2ca
Pipeline #14499 passed with stages
in 7 minutes and 10 seconds
{
// 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
......@@ -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;
......
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);
......
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 {
......
......@@ -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;
......
......@@ -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});
}
}
......@@ -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>-->
......
......@@ -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[]) {
......
......@@ -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));
}
......
......@@ -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"]
},
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment