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

lots of development to sv2

parent 2a260a4f
......@@ -4,8 +4,8 @@
<span class="fill-remaining-space"></span>
<span class="fill-remaining-space"></span>
<!-- <app-siteselection></app-siteselection> -->
<button mat-button *ngIf="authorised" (click)="logout()">Logout</button>
<button mat-button *ngIf="!authorised" (click)="login()">Login</button>
<!-- <button mat-button *ngIf="authorised" (click)="logout()">Logout</button>
<button mat-button *ngIf="!authorised" (click)="login()">Login</button> -->
</mat-toolbar-row>
</mat-toolbar>
......
......@@ -17,7 +17,6 @@ export class AppComponent {
};
ngOnInit() {
setTimeout(() => { this.tesService.authorised.subscribe(authorised => { this.authorised = authorised }); });
// this.tesService.testingAuth.subscribe(testingAuth => { this.testingAuth = testingAuth; console.log('testingAuth updated'+this.testingAuth) });
// this.testingAuth = false;
}
......
......@@ -3,7 +3,7 @@ import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { LauncherComponent, DialogPlaceholder } from './launcher/launcher.component';
import { LauncherComponent } from './launcher/launcher.component';
import { JoblistComponent } from './joblist/joblist.component';
import { MatButtonModule } from '@angular/material';
import { MatFormFieldModule } from '@angular/material';
......@@ -27,6 +27,8 @@ import { SiteselectionComponent } from './siteselection/siteselection.component'
import { TeserrorsComponent } from './teserrors/teserrors.component';
import { AppRoutingModule } from './/app-routing.module';
import { TokenextractorComponent } from './tokenextractor/tokenextractor.component';
import { LogindialogComponent } from './logindialog/logindialog.component';
import { LogoutdialogComponent } from './logoutdialog/logoutdialog.component';
......@@ -38,8 +40,9 @@ import { TokenextractorComponent } from './tokenextractor/tokenextractor.compone
JobComponent,
SiteselectionComponent,
TeserrorsComponent,
DialogPlaceholder,
TokenextractorComponent
TokenextractorComponent,
LogindialogComponent,
LogoutdialogComponent
],
imports: [
BrowserModule,
......@@ -60,7 +63,7 @@ import { TokenextractorComponent } from './tokenextractor/tokenextractor.compone
AppRoutingModule,
],
entryComponents: [ DialogPlaceholder ],
entryComponents: [ LogindialogComponent, LogoutdialogComponent ],
providers: [ StrudelappsService, ComputesitesService, TesService, MatDialog],
bootstrap: [AppComponent]
})
......
......@@ -7,4 +7,18 @@ 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: Strudelapp[];
}
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
}
......@@ -2,7 +2,9 @@ import { Injectable } from '@angular/core';
import { Computesite } from './computesite';
import { COMPUTESITES } from './mock-compute-site';
@Injectable()
@Injectable({
providedIn: 'root',
})
export class ComputesitesService {
constructor() { }
......
import {Computesite} from './computesite';
// Identities are defined by a username on a computer, but rather than just
// 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 {
username: string;
site: Computesite;
authservice: AuthService;
constructor( username: string, site: Computesite) {
this.username = username;
this.site = site;
}
displayName(): string {
return this.username+'@'+this.site.name;
}
repr(): string {
return JSON.stringify([this.username,this.site.cafingerprint,this.site.host]);
}
}
export class AuthToken {
token: string;
authservice: AuthService;
constructor( token: string, authservice: AuthService ) {
this.token = token;
this.authservice = authservice;
}
}
export class KeyCert {
key: string;
cert: string;
authservice: AuthService;
}
export class AuthService {
base: string;
authorise: string;
sign: string;
client_id: string;
}
......@@ -19,15 +19,20 @@ export class JobComponent implements OnInit {
}
ngOnInit() {
console.log('creating job component');
if (this.jobdata.state == "RUNNING") {
this.available = true;
} else {
this.available = false;
}
this.tesService.busy.subscribe(busy => this.busy = busy);
console.log('creating job component complete');
}
onCancel() {
this.jobdata.app = this.strudelAppsService.getApp(this.jobdata.name);
console.log(this.jobdata);
this.tesService.cancel(this.jobdata);
}
......
<div *ngIf="jobs.length == 0">
<div *ngIf="identities.length == 0">
<mat-card>
You don't appear to have any jobs
</mat-card>
Click identity and login to a service to start an application.
</mat-card>
</div>
<div *ngFor="let job of jobs">
<app-job [jobdata]=job></app-job>
<div *ngFor="let id of identities">
<mat-card>
<mat-card-title>{{ id.displayName() }}</mat-card-title>
<div *ngIf="jobs[id.repr()] == undefined || jobs[id.repr()].length == 0 ">
No jobs running yet
</div>
<div *ngFor="let job of jobs[id.repr()]">
<app-job [jobdata]=job></app-job>
</div>
</mat-card>
</div>
......@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
import {TesService} from '../tes.service';
import { Job } from '../job';
import { Observable } from 'rxjs/Observable';
import { Identity } from '../identity';
......@@ -11,16 +12,20 @@ import { Observable } from 'rxjs/Observable';
styleUrls: ['./joblist.component.css']
})
export class JoblistComponent implements OnInit {
public jobs: any[] = [];
public jobs: {[id: string]: Job[] } = {};
public identities: Identity[];
private displayedColumns = ['id'];
private jobsSubscription: any;
private idSubscription: any;
constructor(private tesService: TesService,) { }
constructor(private tesService: TesService,) {
}
ngOnInit() {
this.jobsSubscription = this.tesService.joblist.subscribe(jobs => this.jobs = jobs);
console.log("jobs subscribed by joblist component");
console.log('creating joblist component');
this.jobsSubscription = this.tesService.joblist.subscribe(jobs => this.updateJobs(jobs));
this.idSubscription = this.tesService.identities.subscribe(ids => this.updateIds(ids));
console.log("joblist component complete");
}
public ngOnDestroy(): void {
......@@ -29,21 +34,18 @@ export class JoblistComponent implements OnInit {
}
}
updateIds(identities: Identity[]) {
console.log('update identities');
this.identities = identities;
console.log('update identities complete');
updateJobs(jobs) {
this.jobs = jobs;
console.log("job data received by the joblist component");
console.log(this.jobs);
}
login(){
//Wire this up to the tes login component to get an ssh cert on the tes backend
//This will also tell the TES which site we are using
return;
updateJobs(jobs) {
console.log('updating jobs')
this.jobs = jobs;
console.log('update jobs complete')
}
logout() {
return;
}
}
<div *ngIf="authorised">
<mat-form-field>
<mat-select placeholder="Identity" (selectionChange)="selectId($event)">
<mat-option *ngFor="let id of identities" [value]=id>
{{id.displayName()}}
</mat-option>
<mat-option>
<button mat-button (click)=login()>Login ... </button>
</mat-option>
<mat-option>
<button mat-button (click)=logout()> Logout </button>
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="Application" [(value)]=app>
<mat-option *ngFor="let a of strudelapps" [value]=a>
......@@ -7,12 +20,8 @@
</mat-option>
</mat-select>
</mat-form-field>
<button mat-button (click)=configureResources()>Configure Resources</button>
<button mat-button (click)=configureApp() [disabled]="!app">Configure App</button>
<button mat-button (click)=submitApp() [disabled]="!app">Start</button>
<button mat-button (click)=configureResources() [disabled]="!app || !identity">Configure Resources</button>
<!-- <button mat-button (click)=configureApp() [disabled]="!app || !identity">Configure App</button> -->
<button mat-button (click)=submitApp() [disabled]="!app || !identity">Start</button>
<app-joblist></app-joblist>
</div>
......@@ -3,7 +3,10 @@ import {Strudelapp} from '../strudelapp';
import { StrudelappsService } from '../strudelapps.service';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material';
import { TesService } from '../tes.service';
import {Identity } from '../identity';
import { Identity } from '../identity';
import { Computesite } from '../computesite';
import { LogoutdialogComponent } from '../logoutdialog/logoutdialog.component';
import { LogindialogComponent } from '../logindialog/logindialog.component'
......@@ -18,68 +21,93 @@ export class LauncherComponent implements OnInit {
private app: Strudelapp;
public authorised: boolean;
private identity: Identity;
private identities: Identity[];
constructor(private strudelappsService: StrudelappsService, public dialog: MatDialog, private tesService: TesService) { }
ngOnInit() {
this.loadStrudelapps();
setTimeout( () => { this.tesService.authorised.subscribe(auth => this.authorised = auth); });
constructor( public dialog: MatDialog, private tesService: TesService) {
}
ngOnInit() {
console.log('initialising launcher compoenent');
this.strudelapps = [];
setTimeout( () => { this.tesService.identities.subscribe(identities => this.updateIdentities(identities)); });
console.log('initialising launcher compoenent complete');
configureApp() {
console.log('configuring app for',this.app.name);
this.openDialog('If the application takes any parameters, this will open a new window where you can configure them')
}
configureResources() {
this.openDialog('This will open a new window to configure resource reqests')
}
updateIdentities(identities) {
console.log('updateIdentities in launcher');
this.identities = identities;
console.log('updateIdentities in launcher complete');
submitApp() {
console.log('submitting app for',this.app.name);
this.identity = this.tesService.identities[0];
this.tesService.submit(this.app, this.identity);
// this.openDialog('This is where we should start the app');
}
appselect(a: any) {
console.log('appselect')
this.app = a;
}
login () {
let dialogRef = this.dialog.open(LogindialogComponent, {
width: '250px',
height: '400px',
});
return;
}
logout() {
let dialogRef = this.dialog.open(LogoutdialogComponent, {
width: '250px',
height: '400px',
});
// this.tesService.logout();
// return;
}
loadStrudelapps() {
this.strudelapps = this.strudelappsService.getStrudelapps()
}
openDialog(msg: string ): void {
let dialogRef = this.dialog.open(DialogPlaceholder, {
width: '250px',
height: '400px',
data: { 'msg': msg }
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
});
selectId(event: any) {
console.log('in selectID');
if (!(event.value === undefined) && event.value instanceof(Identity)) {
this.identity=event.value;
this.strudelapps = this.identity.site.appCatalog;
}
console.log('selectID complete');
}
configureResources() {
let configwindow = window.open(this.identity.site.url+'configure/'+this.app.name);
}
}
submitApp() {
this.tesService.getconfig(this.app, this.identity)
.subscribe(resp => {console.log(resp); this.tesService.submit(this.app,this.identity,resp)});
}
@Component({
selector: 'dialog-placeholder',
templateUrl: 'dialog-placeholder.html',
})
export class DialogPlaceholder {
constructor(
public dialogRef: MatDialogRef<DialogPlaceholder>,
@Inject(MAT_DIALOG_DATA) public data: any) { }
onNoClick(): void {
this.dialogRef.close();
}
// openDialog(msg: string ): void {
// let dialogRef = this.dialog.open(LoginDialog, {
// width: '250px',
// height: '400px',
// data: { 'msg': msg }
// });
//
// dialogRef.afterClosed().subscribe(result => {
// console.log('The dialog was closed');
// });
// }
}
// @Component({
// selector: 'dialog-placeholder',
// templateUrl: 'dialog-placeholder.html',
// })
// export class LoginDialog {
//
// constructor(
// public dialogRef: MatDialogRef<LoginDialog>,
// @Inject(MAT_DIALOG_DATA) public data: any) { }
//
// onNoClick(): void {
// this.dialogRef.close();
// }
//
// }
<button mat-button (click)="onLogin()">Login to M3</button>
<button mat-button (click)="onCancel()">Cancel</button>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LogindialogComponent } from './logindialog.component';
describe('LogindialogComponent', () => {
let component: LogindialogComponent;
let fixture: ComponentFixture<LogindialogComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LogindialogComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LogindialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, Inject } from '@angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material';
import { TesService } from '../tes.service';
@Component({
selector: 'app-logindialog',
templateUrl: './logindialog.component.html',
styleUrls: ['./logindialog.component.css']
})
export class LogindialogComponent implements OnInit {
constructor(
public dialogRef: MatDialogRef<LogindialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private tesService: TesService) {
}
ngOnInit() {
}
onLogin() {
this.tesService.login();
}
onCancel() {
this.dialogRef.close();
}
}
<button mat-button (click)="onLogout()">Logout of everything</button>
<button mat-button (click)="onCancel()">Cancel</button>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LogoutdialogComponent } from './logoutdialog.component';
describe('LogoutdialogComponent', () => {
let component: LogoutdialogComponent;
let fixture: ComponentFixture<LogoutdialogComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LogoutdialogComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LogoutdialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, Inject } from '@angular/core';
import { TesService } from '../tes.service';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material';
@Component({
selector: 'app-logoutdialog',
templateUrl: './logoutdialog.component.html',
styleUrls: ['./logoutdialog.component.css']
})
export class LogoutdialogComponent implements OnInit {
constructor(
public dialogRef: MatDialogRef<LogoutdialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private tesService: TesService) {
}
ngOnInit() {
}
onLogout() {
this.tesService.logout();
this.dialogRef.close();
}
onCancel() {
this.dialogRef.close();
}
}
import { Computesite } from './computesite';
import { STRUDELAPPS } from './mock-strudel-app';
export const COMPUTESITES: Computesite[] = [
{ url: 'http://localhost:8080/config', name: 'M3',
{ url: 'https://vm-118-138-240-255.erc.monash.edu.au/m3siteconfig/', name: 'M3',
host: 'm3.massive.org.au',
cafingerprint: 'RSA SHA256:cmDxHrZQSPlBMUUcI/BWmruXho1XOzfXPDHSqVTwV2I' },
cafingerprint: 'RSA SHA256:cmDxHrZQSPlBMUUcI/BWmruXho1XOzfXPDHSqVTwV2I',
appCatalog: STRUDELAPPS }
];
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