Add string constants and improve the default catch of statistics
1. Move ephemeral strings to constants where appropriate 2. Change the switch to a regex to catch the defaults in stats 3. Renamed the websocket modules to match with the backend Change-Id: I9e756bb046c78e6aef393adb83db2d22ebc6a585
This commit is contained in:
parent
023252615e
commit
c13a04669b
@ -16,10 +16,10 @@ import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { MatAccordion } from '@angular/material/expansion';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { IconService } from 'src/services/icon/icon.service';
|
||||
import { WebsocketService } from 'src/services/websocket/websocket.service';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { Dashboard, WsReceiver, WsMessage, WsConstants } from 'src/services/ws/ws.models';
|
||||
import { Log } from 'src/services/log/log.service';
|
||||
import { LogMessage } from 'src/services/log/log-message';
|
||||
import { Dashboard, WSReceiver, WebsocketMessage } from 'src/services/websocket/websocket.models';
|
||||
import { Nav } from './app.models';
|
||||
import { AuthGuard } from 'src/services/auth-guard/auth-guard.service';
|
||||
|
||||
@ -29,12 +29,12 @@ import { AuthGuard } from 'src/services/auth-guard/auth-guard.service';
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
|
||||
export class AppComponent implements OnInit, WSReceiver {
|
||||
export class AppComponent implements OnInit, WsReceiver {
|
||||
@ViewChild(MatAccordion) accordion: MatAccordion;
|
||||
|
||||
className = this.constructor.name;
|
||||
type = 'ui';
|
||||
component = 'any';
|
||||
type = WsConstants.UI;
|
||||
component = WsConstants.ANY;
|
||||
|
||||
currentYear: number;
|
||||
version: string;
|
||||
@ -79,30 +79,30 @@ export class AppComponent implements OnInit, WSReceiver {
|
||||
}];
|
||||
|
||||
constructor(private iconService: IconService,
|
||||
private websocketService: WebsocketService) {
|
||||
private websocketService: WsService) {
|
||||
this.currentYear = new Date().getFullYear();
|
||||
this.version = environment.version;
|
||||
this.websocketService.registerFunctions(this);
|
||||
}
|
||||
|
||||
async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
this.websocketService.printIfToast(message);
|
||||
} else {
|
||||
switch (message.component) {
|
||||
case 'log':
|
||||
case WsConstants.LOG:
|
||||
Log.Debug(new LogMessage('Log message received in app', this.className, message));
|
||||
const panel = document.getElementById('logPanel');
|
||||
panel.appendChild(document.createTextNode(message.message));
|
||||
panel.appendChild(document.createElement('br'));
|
||||
break;
|
||||
case 'initialize':
|
||||
case WsConstants.INITIALIZE:
|
||||
Log.Debug(new LogMessage('Initialize message received in app', this.className, message));
|
||||
if (message.hasOwnProperty('dashboards')) {
|
||||
this.updateDashboards(message.dashboards);
|
||||
}
|
||||
break;
|
||||
case 'keepalive':
|
||||
case WsConstants.KEEPALIVE:
|
||||
Log.Debug(new LogMessage('Keepalive message received in app', this.className, message));
|
||||
break;
|
||||
default:
|
||||
|
@ -18,9 +18,9 @@ import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { WebsocketService } from '../services/websocket/websocket.service';
|
||||
import { WsService } from '../services/ws/ws.service';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
import { MonacoEditorModule, NgxMonacoEditorConfig } from 'ngx-monaco-editor';
|
||||
import { MonacoEditorModule } from 'ngx-monaco-editor';
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
@ -67,7 +67,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
MatTooltipModule
|
||||
],
|
||||
declarations: [AppComponent, TaskComponent],
|
||||
providers: [WebsocketService],
|
||||
providers: [WsService],
|
||||
bootstrap: [AppComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
|
@ -13,10 +13,10 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { WebsocketService } from '../../../services/websocket/websocket.service';
|
||||
import { WebsocketMessage, WSReceiver } from '../../../services/websocket/websocket.models';
|
||||
import { Log } from '../../../services/log/log.service';
|
||||
import { LogMessage } from '../../../services/log/log-message';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsReceiver, WsConstants } from 'src/services/ws/ws.models';
|
||||
import { Log } from 'src/services/log/log.service';
|
||||
import { LogMessage } from 'src/services/log/log-message';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
@ -29,11 +29,10 @@ import { NodeData, PhaseData } from './baremetal.models';
|
||||
styleUrls: ['./baremetal.component.css']
|
||||
})
|
||||
|
||||
export class BaremetalComponent implements WSReceiver, OnInit {
|
||||
export class BaremetalComponent implements WsReceiver, OnInit {
|
||||
className = this.constructor.name;
|
||||
// TODO (aschiefe): extract these strings to constants
|
||||
type = 'ctl';
|
||||
component = 'baremetal';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.BAREMETAL;
|
||||
|
||||
nodeColumns: string[] = ['select', 'name', 'id', 'bmcAddress'];
|
||||
nodeDataSource: MatTableDataSource<NodeData> = new MatTableDataSource();
|
||||
@ -47,16 +46,16 @@ export class BaremetalComponent implements WSReceiver, OnInit {
|
||||
@ViewChild('phaseTableSort', { static: false }) phaseSort: MatSort;
|
||||
@ViewChild('phasePaginator', { static: false }) phasePaginator: MatPaginator;
|
||||
|
||||
constructor(private websocketService: WebsocketService) {
|
||||
constructor(private websocketService: WsService) {
|
||||
this.websocketService.registerFunctions(this);
|
||||
}
|
||||
|
||||
async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
this.websocketService.printIfToast(message);
|
||||
} else {
|
||||
switch (message.subComponent) {
|
||||
case 'getDefaults':
|
||||
case WsConstants.GET_DEFAULTS:
|
||||
this.pushData(message.data);
|
||||
break;
|
||||
default:
|
||||
@ -67,7 +66,7 @@ export class BaremetalComponent implements WSReceiver, OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
const message = new WebsocketMessage(this.type, this.component, 'getDefaults');
|
||||
const message = new WsMessage(this.type, this.component, WsConstants.GET_DEFAULTS);
|
||||
Log.Debug(new LogMessage('Attempting to ask for node data', this.className, message));
|
||||
this.websocketService.sendMessage(message);
|
||||
}
|
||||
@ -178,7 +177,7 @@ export class BaremetalComponent implements WSReceiver, OnInit {
|
||||
|
||||
// retrieve the targets to run the action against
|
||||
// create the websocket message & fire the request to the backend
|
||||
const message = new WebsocketMessage(this.type, this.component, subComponent);
|
||||
const message = new WsMessage(this.type, this.component, subComponent);
|
||||
const displaying = (document.getElementById('displaySelect') as HTMLInputElement).value;
|
||||
const targets: string[] = new Array();
|
||||
if (displaying === 'node') {
|
||||
|
@ -13,10 +13,10 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WebsocketService } from '../../../services/websocket/websocket.service';
|
||||
import { WebsocketMessage, WSReceiver } from '../../../services/websocket/websocket.models';
|
||||
import { Log } from '../../../services/log/log.service';
|
||||
import { LogMessage } from '../../../services/log/log-message';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsReceiver, WsConstants } from 'src/services/ws/ws.models';
|
||||
import { Log } from 'src/services/log/log.service';
|
||||
import { LogMessage } from 'src/services/log/log-message';
|
||||
|
||||
@Component({
|
||||
selector: 'app-cluster',
|
||||
@ -24,18 +24,17 @@ import { LogMessage } from '../../../services/log/log-message';
|
||||
styleUrls: ['./cluster.component.css']
|
||||
})
|
||||
|
||||
export class ClusterComponent implements WSReceiver {
|
||||
export class ClusterComponent implements WsReceiver {
|
||||
className = this.constructor.name;
|
||||
// TODO (aschiefe): extract these strings to constants
|
||||
type = 'ctl';
|
||||
component = 'cluster';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.CLUSTER;
|
||||
|
||||
constructor(private websocketService: WebsocketService) {
|
||||
constructor(private websocketService: WsService) {
|
||||
this.websocketService.registerFunctions(this);
|
||||
}
|
||||
|
||||
async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
this.websocketService.printIfToast(message);
|
||||
} else {
|
||||
switch (message.subComponent) {
|
||||
|
@ -14,9 +14,9 @@
|
||||
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Context, ContextOptions } from '../config.models';
|
||||
import { WebsocketService } from '../../../../services/websocket/websocket.service';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { WebsocketMessage } from 'src/services/websocket/websocket.models';
|
||||
import { WsMessage, WsConstants } from 'src/services/ws/ws.models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-config-context',
|
||||
@ -25,8 +25,8 @@ import { WebsocketMessage } from 'src/services/websocket/websocket.models';
|
||||
})
|
||||
export class ConfigContextComponent implements OnInit {
|
||||
@Input() context: Context;
|
||||
type = 'ctl';
|
||||
component = 'config';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.CONFIG;
|
||||
|
||||
locked = true;
|
||||
|
||||
@ -38,7 +38,7 @@ export class ConfigContextComponent implements OnInit {
|
||||
|
||||
controlsArray = [this.name, this.contextKubeconf, this.manifest, this.managementConfiguration, this.encryptionConfig];
|
||||
|
||||
constructor(private websocketService: WebsocketService) {}
|
||||
constructor(private websocketService: WsService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.name.setValue(this.context.name);
|
||||
@ -68,7 +68,7 @@ export class ConfigContextComponent implements OnInit {
|
||||
EncryptionConfig: this.encryptionConfig.value,
|
||||
};
|
||||
|
||||
const msg = new WebsocketMessage(this.type, this.component, 'setContext');
|
||||
const msg = new WsMessage(this.type, this.component, WsConstants.SET_CONTEXT);
|
||||
msg.data = JSON.parse(JSON.stringify(opts));
|
||||
msg.name = this.name.value;
|
||||
|
||||
@ -77,7 +77,7 @@ export class ConfigContextComponent implements OnInit {
|
||||
}
|
||||
|
||||
useContext(name: string): void {
|
||||
const msg = new WebsocketMessage(this.type, this.component, 'useContext');
|
||||
const msg = new WsMessage(this.type, this.component, WsConstants.USE_CONTEXT);
|
||||
msg.name = name;
|
||||
this.websocketService.sendMessage(msg);
|
||||
}
|
||||
|
@ -15,8 +15,8 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { EncryptionConfig, EncryptionConfigOptions } from '../config.models';
|
||||
import { WebsocketService } from '../../../../services/websocket/websocket.service';
|
||||
import { WebsocketMessage } from '../../../../services/websocket/websocket.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsConstants } from 'src/services/ws/ws.models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-config-encryption',
|
||||
@ -25,8 +25,8 @@ import { WebsocketMessage } from '../../../../services/websocket/websocket.model
|
||||
})
|
||||
export class ConfigEncryptionComponent implements OnInit {
|
||||
@Input() config: EncryptionConfig;
|
||||
type = 'ctl';
|
||||
component = 'config';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.CONFIG;
|
||||
|
||||
locked = true;
|
||||
name = new FormControl({value: '', disabled: true});
|
||||
@ -37,7 +37,7 @@ export class ConfigEncryptionComponent implements OnInit {
|
||||
|
||||
controlsArray = [this.encryptionKeyPath, this.decryptionKeyPath, this.keySecretName, this.keySecretNamespace];
|
||||
|
||||
constructor(private websocketService: WebsocketService) {}
|
||||
constructor(private websocketService: WsService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.name.setValue(this.config.name);
|
||||
@ -68,7 +68,7 @@ export class ConfigEncryptionComponent implements OnInit {
|
||||
KeySecretNamespace: this.keySecretNamespace.value,
|
||||
};
|
||||
|
||||
const msg = new WebsocketMessage(this.type, this.component, 'setEncryptionConfig');
|
||||
const msg = new WsMessage(this.type, this.component, WsConstants.SET_ENCRYPTION_CONFIG);
|
||||
msg.data = JSON.parse(JSON.stringify(opts));
|
||||
msg.name = this.name.value;
|
||||
|
||||
|
@ -14,8 +14,8 @@
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { WebsocketService } from '../../../../services/websocket/websocket.service';
|
||||
import { WebsocketMessage } from '../../../../services/websocket/websocket.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsConstants } from 'src/services/ws/ws.models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-config-init',
|
||||
@ -23,22 +23,22 @@ import { WebsocketMessage } from '../../../../services/websocket/websocket.model
|
||||
styleUrls: ['./config-init.component.css']
|
||||
})
|
||||
export class ConfigInitComponent {
|
||||
type = 'ctl';
|
||||
component = 'config';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.CONFIG;
|
||||
|
||||
initValue = new FormControl('');
|
||||
specifyValue = new FormControl('');
|
||||
|
||||
constructor(private websocketService: WebsocketService) {}
|
||||
constructor(private websocketService: WsService) {}
|
||||
|
||||
initAirshipConfig(): void {
|
||||
const msg = new WebsocketMessage(this.type, this.component, 'init');
|
||||
const msg = new WsMessage(this.type, this.component, WsConstants.INIT);
|
||||
msg.message = this.initValue.value;
|
||||
this.websocketService.sendMessage(msg);
|
||||
}
|
||||
|
||||
setAirshipConfig(): void {
|
||||
const msg = new WebsocketMessage(this.type, this.component, 'setAirshipConfig');
|
||||
const msg = new WsMessage(this.type, this.component, WsConstants.SET_AIRSHIP_CONFIG);
|
||||
msg.message = this.specifyValue.value;
|
||||
this.websocketService.sendMessage(msg);
|
||||
}
|
||||
|
@ -15,8 +15,8 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { ManagementConfig } from '../config.models';
|
||||
import { FormControl, Validators } from '@angular/forms';
|
||||
import { WebsocketService } from 'src/services/websocket/websocket.service';
|
||||
import { WebsocketMessage } from 'src/services/websocket/websocket.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsConstants } from 'src/services/ws/ws.models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-config-management',
|
||||
@ -25,8 +25,8 @@ import { WebsocketMessage } from 'src/services/websocket/websocket.models';
|
||||
})
|
||||
export class ConfigManagementComponent implements OnInit {
|
||||
@Input() config: ManagementConfig;
|
||||
msgType = 'ctl';
|
||||
component = 'config';
|
||||
msgType = WsConstants.CTL;
|
||||
component = WsConstants.CONFIG;
|
||||
|
||||
locked = true;
|
||||
|
||||
@ -39,7 +39,7 @@ export class ConfigManagementComponent implements OnInit {
|
||||
|
||||
controlsArray = [this.name, this.insecure, this.systemRebootDelay, this.systemActionRetries, this.type, this.useproxy];
|
||||
|
||||
constructor(private websocketService: WebsocketService) { }
|
||||
constructor(private websocketService: WsService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.name.setValue(this.config.name);
|
||||
@ -63,7 +63,7 @@ export class ConfigManagementComponent implements OnInit {
|
||||
}
|
||||
|
||||
setManagementConfig(): void {
|
||||
const msg = new WebsocketMessage(this.msgType, this.component, 'setManagementConfig');
|
||||
const msg = new WsMessage(this.msgType, this.component, WsConstants.SET_MANAGEMENT_CONFIG);
|
||||
msg.name = this.name.value;
|
||||
|
||||
const cfg: ManagementConfig = {
|
||||
|
@ -15,8 +15,8 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Manifest, ManifestOptions, Repository } from '../config.models';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { WebsocketService } from 'src/services/websocket/websocket.service';
|
||||
import { WebsocketMessage } from 'src/services/websocket/websocket.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsConstants } from 'src/services/ws/ws.models';
|
||||
|
||||
|
||||
@Component({
|
||||
@ -27,8 +27,8 @@ import { WebsocketMessage } from 'src/services/websocket/websocket.models';
|
||||
export class ConfigManifestComponent implements OnInit {
|
||||
@Input() manifest: Manifest;
|
||||
|
||||
type = 'ctl';
|
||||
component = 'config';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.CONFIG;
|
||||
|
||||
locked = true;
|
||||
Name = new FormControl({value: '', disabled: true});
|
||||
@ -59,7 +59,7 @@ export class ConfigManifestComponent implements OnInit {
|
||||
this.MetadataPath
|
||||
];
|
||||
|
||||
constructor(private websocketService: WebsocketService) { }
|
||||
constructor(private websocketService: WsService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.Name.setValue(this.manifest.name);
|
||||
@ -97,7 +97,7 @@ export class ConfigManifestComponent implements OnInit {
|
||||
}
|
||||
|
||||
setManifest(): void {
|
||||
const msg = new WebsocketMessage(this.type, this.component, 'setManifest');
|
||||
const msg = new WsMessage(this.type, this.component, WsConstants.SET_MANIFEST);
|
||||
msg.name = this.manifest.name;
|
||||
|
||||
// TODO(mfuller): since "Force" and "IsPhase" can only be set by passing in
|
||||
|
@ -13,22 +13,21 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WebsocketService } from '../../../services/websocket/websocket.service';
|
||||
import { WebsocketMessage, WSReceiver } from '../../../services/websocket/websocket.models';
|
||||
import { Log } from '../../../services/log/log.service';
|
||||
import { LogMessage } from '../../../services/log/log-message';
|
||||
import { Log } from 'src/services/log/log.service';
|
||||
import { LogMessage } from 'src/services/log/log-message';
|
||||
import { Context, ManagementConfig, Manifest, EncryptionConfig } from './config.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsReceiver, WsConstants } from 'src/services/ws/ws.models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bare-metal',
|
||||
templateUrl: './config.component.html',
|
||||
})
|
||||
|
||||
export class ConfigComponent implements WSReceiver, OnInit {
|
||||
export class ConfigComponent implements WsReceiver, OnInit {
|
||||
className = this.constructor.name;
|
||||
// TODO (aschiefe): extract these strings to constants
|
||||
type = 'ctl';
|
||||
component = 'config';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.CONFIG;
|
||||
|
||||
airshipConfigPath: string;
|
||||
|
||||
@ -38,7 +37,7 @@ export class ConfigComponent implements WSReceiver, OnInit {
|
||||
managementConfigs: ManagementConfig[] = [];
|
||||
encryptionConfigs: EncryptionConfig[] = [];
|
||||
|
||||
constructor(private websocketService: WebsocketService) {
|
||||
constructor(private websocketService: WsService) {
|
||||
this.websocketService.registerFunctions(this);
|
||||
}
|
||||
|
||||
@ -46,50 +45,50 @@ export class ConfigComponent implements WSReceiver, OnInit {
|
||||
this.getConfig();
|
||||
}
|
||||
|
||||
async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
this.websocketService.printIfToast(message);
|
||||
} else {
|
||||
switch (message.subComponent) {
|
||||
case 'init':
|
||||
case WsConstants.INIT:
|
||||
this.websocketService.printIfToast(message);
|
||||
this.getConfig();
|
||||
break;
|
||||
case 'setAirshipConfig':
|
||||
case WsConstants.SET_AIRSHIP_CONFIG:
|
||||
this.websocketService.printIfToast(message);
|
||||
this.getConfig();
|
||||
break;
|
||||
case 'getAirshipConfigPath':
|
||||
case WsConstants.GET_AIRSHIP_CONFIG_PATH:
|
||||
this.airshipConfigPath = message.message;
|
||||
break;
|
||||
case 'getCurrentContext':
|
||||
case WsConstants.GET_CURRENT_CONTEXT:
|
||||
this.currentContext = message.message;
|
||||
break;
|
||||
case 'getContexts':
|
||||
case WsConstants.GET_CONTEXTS:
|
||||
Object.assign(this.contexts, message.data);
|
||||
break;
|
||||
case 'getManifests':
|
||||
case WsConstants.GET_MANIFESTS:
|
||||
Object.assign(this.manifests, message.data);
|
||||
break;
|
||||
case 'getEncryptionConfigs':
|
||||
case WsConstants.GET_ENCRYPTION_CONFIGS:
|
||||
Object.assign(this.encryptionConfigs, message.data);
|
||||
break;
|
||||
case 'getManagementConfigs':
|
||||
case WsConstants.GET_MANAGEMENT_CONFIGS:
|
||||
Object.assign(this.managementConfigs, message.data);
|
||||
break;
|
||||
case 'useContext':
|
||||
case WsConstants.USE_CONTEXT:
|
||||
this.getCurrentContext();
|
||||
break;
|
||||
case 'setContext':
|
||||
case WsConstants.SET_CONTEXT:
|
||||
this.websocketService.printIfToast(message);
|
||||
break;
|
||||
case 'setEncryptionConfig':
|
||||
case WsConstants.SET_ENCRYPTION_CONFIG:
|
||||
this.websocketService.printIfToast(message);
|
||||
break;
|
||||
case 'setManifest':
|
||||
case WsConstants.SET_MANIFEST:
|
||||
this.websocketService.printIfToast(message);
|
||||
break;
|
||||
case 'setManagementConfig':
|
||||
case WsConstants.SET_MANAGEMENT_CONFIG:
|
||||
this.websocketService.printIfToast(message);
|
||||
break;
|
||||
default:
|
||||
@ -109,38 +108,38 @@ export class ConfigComponent implements WSReceiver, OnInit {
|
||||
}
|
||||
|
||||
getAirshipConfigPath(): void {
|
||||
this.websocketService.sendMessage(new WebsocketMessage(
|
||||
this.websocketService.sendMessage(new WsMessage(
|
||||
this.type, this.component, 'getAirshipConfigPath')
|
||||
);
|
||||
}
|
||||
|
||||
getCurrentContext(): void {
|
||||
this.websocketService.sendMessage(new WebsocketMessage(
|
||||
this.type, this.component, 'getCurrentContext')
|
||||
this.websocketService.sendMessage(new WsMessage(
|
||||
this.type, this.component, WsConstants.GET_CURRENT_CONTEXT)
|
||||
);
|
||||
}
|
||||
|
||||
getContexts(): void {
|
||||
this.websocketService.sendMessage(new WebsocketMessage(
|
||||
this.type, this.component, 'getContexts')
|
||||
this.websocketService.sendMessage(new WsMessage(
|
||||
this.type, this.component, WsConstants.GET_CONTEXTS)
|
||||
);
|
||||
}
|
||||
|
||||
getManifests(): void {
|
||||
this.websocketService.sendMessage(new WebsocketMessage(
|
||||
this.type, this.component, 'getManifests')
|
||||
this.websocketService.sendMessage(new WsMessage(
|
||||
this.type, this.component, WsConstants.GET_MANIFESTS)
|
||||
);
|
||||
}
|
||||
|
||||
getEncryptionConfigs(): void {
|
||||
this.websocketService.sendMessage(new WebsocketMessage(
|
||||
this.type, this.component, 'getEncryptionConfigs')
|
||||
this.websocketService.sendMessage(new WsMessage(
|
||||
this.type, this.component, WsConstants.GET_ENCRYPTION_CONFIGS)
|
||||
);
|
||||
}
|
||||
|
||||
getManagementConfigs(): void {
|
||||
this.websocketService.sendMessage(new WebsocketMessage(
|
||||
this.type, this.component, 'getManagementConfigs')
|
||||
this.websocketService.sendMessage(new WsMessage(
|
||||
this.type, this.component, WsConstants.GET_MANAGEMENT_CONFIGS)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -21,35 +21,35 @@ import { DocumentComponent } from './document/document.component';
|
||||
import { ImageComponent } from './image/image.component';
|
||||
import { PhaseComponent } from './phase/phase.component';
|
||||
import { SecretComponent } from './secret/secret.component';
|
||||
|
||||
import { WsConstants } from 'src/services/ws/ws.models';
|
||||
import { AuthGuard } from 'src/services/auth-guard/auth-guard.service';
|
||||
|
||||
const routes: Routes = [{
|
||||
path: 'baremetal',
|
||||
path: WsConstants.BAREMETAL,
|
||||
canActivate: [AuthGuard],
|
||||
component: BaremetalComponent
|
||||
}, {
|
||||
path: 'cluster',
|
||||
path: WsConstants.CLUSTER,
|
||||
canActivate: [AuthGuard],
|
||||
component: ClusterComponent,
|
||||
}, {
|
||||
path: 'config',
|
||||
path: WsConstants.CONFIG,
|
||||
canActivate: [AuthGuard],
|
||||
component: ConfigComponent,
|
||||
}, {
|
||||
path: 'documents',
|
||||
path: WsConstants.DOCUMENTS,
|
||||
canActivate: [AuthGuard],
|
||||
component: DocumentComponent,
|
||||
}, {
|
||||
path: 'image',
|
||||
path: WsConstants.IMAGE,
|
||||
canActivate: [AuthGuard],
|
||||
component: ImageComponent,
|
||||
}, {
|
||||
path: 'phase',
|
||||
path: WsConstants.PHASE,
|
||||
canActivate: [AuthGuard],
|
||||
component: PhaseComponent,
|
||||
}, {
|
||||
path: 'secret',
|
||||
path: WsConstants.SECRET,
|
||||
canActivate: [AuthGuard],
|
||||
component: SecretComponent,
|
||||
}];
|
||||
|
@ -12,11 +12,11 @@
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
import {Component} from '@angular/core';
|
||||
import {WebsocketService} from '../../../services/websocket/websocket.service';
|
||||
import {WebsocketMessage, WSReceiver} from '../../../services/websocket/websocket.models';
|
||||
import {Log} from '../../../services/log/log.service';
|
||||
import {LogMessage} from '../../../services/log/log-message';
|
||||
import { Component } from '@angular/core';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsReceiver, WsConstants } from 'src/services/ws/ws.models';
|
||||
import { Log } from 'src/services/log/log.service';
|
||||
import { LogMessage } from 'src/services/log/log-message';
|
||||
|
||||
@Component({
|
||||
selector: 'app-document',
|
||||
@ -24,24 +24,23 @@ import {LogMessage} from '../../../services/log/log-message';
|
||||
styleUrls: ['./document.component.css']
|
||||
})
|
||||
|
||||
export class DocumentComponent implements WSReceiver {
|
||||
export class DocumentComponent implements WsReceiver {
|
||||
className = this.constructor.name;
|
||||
statusMsg: string;
|
||||
|
||||
type = 'ctl';
|
||||
component = 'document';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.DOCUMENT;
|
||||
activeLink = 'overview';
|
||||
|
||||
constructor(private websocketService: WebsocketService) {
|
||||
constructor(private websocketService: WsService) {
|
||||
this.websocketService.registerFunctions(this);
|
||||
}
|
||||
|
||||
public async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
public async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
this.websocketService.printIfToast(message);
|
||||
} else {
|
||||
switch (message.subComponent) {
|
||||
case 'pull':
|
||||
case WsConstants.PULL:
|
||||
this.statusMsg = 'Document pull was a ' + message.message;
|
||||
const button = (document.getElementById('DocPullBtn') as HTMLInputElement);
|
||||
button.removeAttribute('disabled');
|
||||
@ -55,7 +54,7 @@ export class DocumentComponent implements WSReceiver {
|
||||
|
||||
documentPull(): void {
|
||||
this.statusMsg = '';
|
||||
this.websocketService.sendMessage(new WebsocketMessage(this.type, this.component, 'pull'));
|
||||
this.websocketService.sendMessage(new WsMessage(this.type, this.component, WsConstants.PULL));
|
||||
const button = (document.getElementById('DocPullBtn') as HTMLInputElement);
|
||||
button.setAttribute('disabled', 'disabled');
|
||||
}
|
||||
|
@ -13,8 +13,8 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WebsocketService } from 'src/services/websocket/websocket.service';
|
||||
import { WebsocketMessage, WSReceiver } from 'src/services/websocket/websocket.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsReceiver, WsConstants } from 'src/services/ws/ws.models';
|
||||
import { Log } from 'src/services/log/log.service';
|
||||
import { LogMessage } from 'src/services/log/log-message';
|
||||
|
||||
@ -24,19 +24,18 @@ import { LogMessage } from 'src/services/log/log-message';
|
||||
styleUrls: ['./image.component.css']
|
||||
})
|
||||
|
||||
export class ImageComponent implements WSReceiver {
|
||||
export class ImageComponent implements WsReceiver {
|
||||
className = this.constructor.name;
|
||||
// TODO (aschiefe): extract these strings to constants
|
||||
type = 'ctl';
|
||||
component = 'image';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.IMAGE;
|
||||
statusMsg: string;
|
||||
|
||||
constructor(private websocketService: WebsocketService) {
|
||||
constructor(private websocketService: WsService) {
|
||||
this.websocketService.registerFunctions(this);
|
||||
}
|
||||
|
||||
async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
this.websocketService.printIfToast(message);
|
||||
} else {
|
||||
// TODO (aschiefe): determine what should be notifications and what should be 86ed
|
||||
@ -45,6 +44,6 @@ export class ImageComponent implements WSReceiver {
|
||||
}
|
||||
|
||||
generateIso(): void {
|
||||
this.websocketService.sendMessage(new WebsocketMessage(this.type, this.component, 'generate'));
|
||||
this.websocketService.sendMessage(new WsMessage(this.type, this.component, WsConstants.GENERATE));
|
||||
}
|
||||
}
|
||||
|
@ -12,12 +12,12 @@
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {MatDialogRef} from '@angular/material/dialog';
|
||||
import {KustomNode} from '../phase.models';
|
||||
import {WebsocketMessage} from '../../../../services/websocket/websocket.models';
|
||||
import {WebsocketService} from '../../../../services/websocket/websocket.service';
|
||||
import {FormControl, FormGroup} from '@angular/forms';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { KustomNode } from '../phase.models';
|
||||
import { WsMessage, WsConstants } from 'src/services/ws/ws.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-phase-viewer',
|
||||
@ -50,7 +50,7 @@ export class PhaseViewerComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<PhaseViewerComponent>,
|
||||
private websocketService: WebsocketService) {}
|
||||
private websocketService: WsService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.bundleYaml = this.yaml;
|
||||
@ -67,20 +67,20 @@ export class PhaseViewerComponent implements OnInit {
|
||||
|
||||
setModel(val: string): void {
|
||||
switch (val) {
|
||||
case 'bundle':
|
||||
case WsConstants.BUNDLE:
|
||||
this.yaml = this.bundleYaml;
|
||||
break;
|
||||
case 'executor':
|
||||
case WsConstants.EXECUTOR:
|
||||
this.yaml = this.executorYaml;
|
||||
break;
|
||||
case 'details':
|
||||
case WsConstants.DETAILS:
|
||||
this.yaml = this.phaseDetails;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
getDocumentsBySelector(selector: string): void {
|
||||
const msg = new WebsocketMessage('ctl', 'phase', 'getDocumentsBySelector');
|
||||
const msg = new WsMessage(WsConstants.CTL, WsConstants.PHASE, WsConstants.GET_DOCUMENT_BY_SELECTOR);
|
||||
msg.message = selector;
|
||||
msg.id = this.id;
|
||||
this.websocketService.sendMessage(msg);
|
||||
@ -88,7 +88,7 @@ export class PhaseViewerComponent implements OnInit {
|
||||
|
||||
getYaml(id: string): void {
|
||||
this.yaml = null;
|
||||
const msg = new WebsocketMessage('ctl', 'phase', 'getYaml');
|
||||
const msg = new WsMessage(WsConstants.CTL, WsConstants.PHASE, WsConstants.GET_YAML);
|
||||
msg.id = id;
|
||||
msg.message = 'rendered';
|
||||
this.websocketService.sendMessage(msg);
|
||||
|
@ -12,19 +12,19 @@
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {PhaseComponent} from './phase.component';
|
||||
import {MatTabsModule} from '@angular/material/tabs';
|
||||
import {MatTreeModule} from '@angular/material/tree';
|
||||
import {MatButtonModule} from '@angular/material/button';
|
||||
import {MatButtonToggleModule} from '@angular/material/button-toggle';
|
||||
import {MatIconModule} from '@angular/material/icon';
|
||||
import {MonacoEditorModule} from 'ngx-monaco-editor';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {ToastrModule} from 'ngx-toastr';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {MatCardModule} from '@angular/material/card';
|
||||
import {MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { PhaseComponent } from './phase.component';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { MatTreeModule } from '@angular/material/tree';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MonacoEditorModule } from 'ngx-monaco-editor';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
|
@ -12,17 +12,17 @@
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
import {Component} from '@angular/core';
|
||||
import {WebsocketService} from '../../../services/websocket/websocket.service';
|
||||
import {WebsocketMessage, WSReceiver} from '../../../services/websocket/websocket.models';
|
||||
import {Log} from '../../../services/log/log.service';
|
||||
import {LogMessage} from '../../../services/log/log-message';
|
||||
import {KustomNode, RunOptions} from './phase.models';
|
||||
import {NestedTreeControl} from '@angular/cdk/tree';
|
||||
import {MatTreeNestedDataSource} from '@angular/material/tree';
|
||||
import { Component } from '@angular/core';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsReceiver, WsConstants } from 'src/services/ws/ws.models';
|
||||
import { Log } from 'src/services/log/log.service';
|
||||
import { LogMessage } from 'src/services/log/log-message';
|
||||
import { KustomNode, RunOptions } from './phase.models';
|
||||
import { NestedTreeControl } from '@angular/cdk/tree';
|
||||
import { MatTreeNestedDataSource } from '@angular/material/tree';
|
||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import { PhaseViewerComponent } from './phase-viewer/phase-viewer.component';
|
||||
import {PhaseRunnerComponent} from './phase-runner/phase-runner.component';
|
||||
import { PhaseRunnerComponent } from './phase-runner/phase-runner.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-phase',
|
||||
@ -30,7 +30,7 @@ import {PhaseRunnerComponent} from './phase-runner/phase-runner.component';
|
||||
styleUrls: ['./phase.component.css']
|
||||
})
|
||||
|
||||
export class PhaseComponent implements WSReceiver {
|
||||
export class PhaseComponent implements WsReceiver {
|
||||
className = this.constructor.name;
|
||||
statusMsg: string;
|
||||
loading: boolean;
|
||||
@ -39,8 +39,8 @@ export class PhaseComponent implements WSReceiver {
|
||||
phaseViewerRef: MatDialogRef<PhaseViewerComponent, any>;
|
||||
phaseRunnerRef: MatDialogRef<PhaseRunnerComponent, any>;
|
||||
|
||||
type = 'ctl';
|
||||
component = 'phase';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.PHASE;
|
||||
activeLink = 'overview';
|
||||
|
||||
targetPath: string;
|
||||
@ -66,46 +66,46 @@ export class PhaseComponent implements WSReceiver {
|
||||
});
|
||||
}
|
||||
|
||||
constructor(private websocketService: WebsocketService, public dialog: MatDialog) {
|
||||
constructor(private websocketService: WsService, public dialog: MatDialog) {
|
||||
this.websocketService.registerFunctions(this);
|
||||
this.getTarget();
|
||||
this.getPhaseTree(); // load the source first
|
||||
}
|
||||
|
||||
public async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
public async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
this.websocketService.printIfToast(message);
|
||||
this.loading = false;
|
||||
if (message.subComponent === 'run') {
|
||||
if (message.subComponent === WsConstants.RUN) {
|
||||
this.toggleNode(message.id);
|
||||
}
|
||||
} else {
|
||||
switch (message.subComponent) {
|
||||
case 'getTarget':
|
||||
case WsConstants.GET_TARGET:
|
||||
this.targetPath = message.message;
|
||||
break;
|
||||
case 'getPhaseTree':
|
||||
case WsConstants.GET_PHASE_TREE:
|
||||
this.handleGetPhaseTree(message.data);
|
||||
break;
|
||||
case 'getPhase':
|
||||
case WsConstants.GET_PHASE:
|
||||
this.handleGetPhase(message);
|
||||
break;
|
||||
case 'getYaml':
|
||||
case WsConstants.GET_YAML:
|
||||
this.handleGetYaml(message);
|
||||
break;
|
||||
case 'getDocumentsBySelector':
|
||||
case WsConstants.GET_DOCUMENT_BY_SELECTOR:
|
||||
this.handleGetDocumentsBySelector(message);
|
||||
break;
|
||||
case 'getExecutorDoc':
|
||||
case WsConstants.GET_EXECUTOR_DOC:
|
||||
this.handleGetExecutorDoc(message);
|
||||
break;
|
||||
case 'yamlWrite':
|
||||
case WsConstants.YAML_WRITE:
|
||||
this.handleYamlWrite(message);
|
||||
break;
|
||||
case 'validatePhase':
|
||||
case WsConstants.VALIDATE_PHASE:
|
||||
this.handleValidatePhase(message);
|
||||
break;
|
||||
case 'run':
|
||||
case WsConstants.RUN:
|
||||
this.handleRunPhase(message);
|
||||
break;
|
||||
default:
|
||||
@ -115,11 +115,11 @@ export class PhaseComponent implements WSReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
handleValidatePhase(message: WebsocketMessage): void {
|
||||
handleValidatePhase(message: WsMessage): void {
|
||||
this.websocketService.printIfToast(message);
|
||||
}
|
||||
|
||||
handleRunPhase(message: WebsocketMessage): void {
|
||||
handleRunPhase(message: WsMessage): void {
|
||||
this.toggleNode(message.id);
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ export class PhaseComponent implements WSReceiver {
|
||||
this.dataSource.data = this.phaseTree;
|
||||
}
|
||||
|
||||
handleGetPhase(message: WebsocketMessage): void {
|
||||
handleGetPhase(message: WsMessage): void {
|
||||
this.loading = false;
|
||||
let yaml = '';
|
||||
if (message.yaml !== '' && message.yaml !== undefined) {
|
||||
@ -138,16 +138,16 @@ export class PhaseComponent implements WSReceiver {
|
||||
this.phaseViewerRef = this.openPhaseDialog(message.id, message.name, message.details, yaml);
|
||||
}
|
||||
|
||||
handleGetExecutorDoc(message: WebsocketMessage): void {
|
||||
handleGetExecutorDoc(message: WsMessage): void {
|
||||
this.phaseViewerRef.componentInstance.executorYaml = atob(message.yaml);
|
||||
}
|
||||
|
||||
handleGetDocumentsBySelector(message: WebsocketMessage): void {
|
||||
handleGetDocumentsBySelector(message: WsMessage): void {
|
||||
this.phaseViewerRef.componentInstance.loading = false;
|
||||
Object.assign(this.phaseViewerRef.componentInstance.results, message.data);
|
||||
}
|
||||
|
||||
handleGetYaml(message: WebsocketMessage): void {
|
||||
handleGetYaml(message: WsMessage): void {
|
||||
if (message.message === 'rendered') {
|
||||
this.phaseViewerRef.componentInstance.yaml = atob(message.yaml);
|
||||
} else {
|
||||
@ -158,7 +158,7 @@ export class PhaseComponent implements WSReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
handleYamlWrite(message: WebsocketMessage): void {
|
||||
handleYamlWrite(message: WsMessage): void {
|
||||
this.changeEditorContents((message.yaml));
|
||||
this.setTitle(message.name);
|
||||
this.currentDocId = message.id;
|
||||
@ -176,7 +176,7 @@ export class PhaseComponent implements WSReceiver {
|
||||
}
|
||||
|
||||
saveYaml(): void {
|
||||
const websocketMessage = this.newMessage('yamlWrite');
|
||||
const websocketMessage = this.newMessage(WsConstants.YAML_WRITE);
|
||||
websocketMessage.id = this.currentDocId;
|
||||
websocketMessage.name = this.editorTitle;
|
||||
websocketMessage.yaml = btoa(this.code);
|
||||
@ -185,7 +185,7 @@ export class PhaseComponent implements WSReceiver {
|
||||
|
||||
getPhaseTree(): void {
|
||||
this.loading = true;
|
||||
const websocketMessage = this.newMessage('getPhaseTree');
|
||||
const websocketMessage = this.newMessage(WsConstants.GET_PHASE_TREE);
|
||||
this.websocketService.sendMessage(websocketMessage);
|
||||
}
|
||||
|
||||
@ -229,29 +229,23 @@ export class PhaseComponent implements WSReceiver {
|
||||
|
||||
}
|
||||
|
||||
getPhaseDetails(id: object): void {
|
||||
const msg = this.newMessage('getPhaseDetails');
|
||||
msg.id = JSON.stringify(id);
|
||||
this.websocketService.sendMessage(msg);
|
||||
}
|
||||
|
||||
getPhase(id: object): void {
|
||||
this.loading = true;
|
||||
const msg = this.newMessage('getPhase');
|
||||
const msg = this.newMessage(WsConstants.GET_PHASE);
|
||||
msg.id = JSON.stringify(id);
|
||||
this.websocketService.sendMessage(msg);
|
||||
}
|
||||
|
||||
getYaml(id: string): void {
|
||||
this.code = null;
|
||||
const msg = this.newMessage('getYaml');
|
||||
const msg = this.newMessage(WsConstants.GET_YAML);
|
||||
msg.id = id;
|
||||
msg.message = 'source';
|
||||
this.websocketService.sendMessage(msg);
|
||||
}
|
||||
|
||||
getExecutorDoc(id: object): void {
|
||||
const msg = this.newMessage('getExecutorDoc');
|
||||
const msg = this.newMessage(WsConstants.GET_DOCUMENT_BY_SELECTOR);
|
||||
msg.id = JSON.stringify(id);
|
||||
this.websocketService.sendMessage(msg);
|
||||
}
|
||||
@ -262,7 +256,7 @@ export class PhaseComponent implements WSReceiver {
|
||||
}
|
||||
|
||||
getTarget(): void {
|
||||
const websocketMessage = this.newMessage('getTarget');
|
||||
const websocketMessage = this.newMessage(WsConstants.GET_TARGET);
|
||||
this.websocketService.sendMessage(websocketMessage);
|
||||
}
|
||||
|
||||
@ -270,7 +264,7 @@ export class PhaseComponent implements WSReceiver {
|
||||
// before actually running the phase
|
||||
runPhase(node: KustomNode, opts: RunOptions): void {
|
||||
node.running = true;
|
||||
const msg = this.newMessage('run');
|
||||
const msg = this.newMessage(WsConstants.RUN);
|
||||
msg.id = JSON.stringify(node.phaseId);
|
||||
if (opts !== undefined) {
|
||||
msg.data = JSON.parse(JSON.stringify(opts));
|
||||
@ -279,13 +273,13 @@ export class PhaseComponent implements WSReceiver {
|
||||
}
|
||||
|
||||
validatePhase(id: object): void {
|
||||
const msg = this.newMessage('validatePhase');
|
||||
const msg = this.newMessage(WsConstants.VALIDATE_PHASE);
|
||||
msg.id = JSON.stringify(id);
|
||||
this.websocketService.sendMessage(msg);
|
||||
}
|
||||
|
||||
newMessage(subComponent: string): WebsocketMessage {
|
||||
return new WebsocketMessage(this.type, this.component, subComponent);
|
||||
newMessage(subComponent: string): WsMessage {
|
||||
return new WsMessage(this.type, this.component, subComponent);
|
||||
}
|
||||
|
||||
findNode(node: KustomNode, id: string): KustomNode {
|
||||
|
@ -13,13 +13,13 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { WebsocketService } from 'src/services/websocket/websocket.service';
|
||||
import { WebsocketMessage, WSReceiver } from 'src/services/websocket/websocket.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsMessage, WsReceiver, WsConstants } from 'src/services/ws/ws.models';
|
||||
import { Log } from 'src/services/log/log.service';
|
||||
import { LogMessage } from 'src/services/log/log-message';
|
||||
import { MatStepper } from '@angular/material/stepper';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import {STEPPER_GLOBAL_OPTIONS, StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||
import { STEPPER_GLOBAL_OPTIONS, StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||
|
||||
@Component({
|
||||
selector: 'app-secret',
|
||||
@ -30,11 +30,10 @@ import {STEPPER_GLOBAL_OPTIONS, StepperSelectionEvent } from '@angular/cdk/stepp
|
||||
}]
|
||||
})
|
||||
|
||||
export class SecretComponent implements WSReceiver, OnInit {
|
||||
export class SecretComponent implements WsReceiver, OnInit {
|
||||
className = this.constructor.name;
|
||||
// TODO (aschiefe): extract these strings to constants
|
||||
type = 'ctl';
|
||||
component = 'secret';
|
||||
type = WsConstants.CTL;
|
||||
component = WsConstants.SECRET;
|
||||
|
||||
// form groups, these control the stepper and the validators for the inputs
|
||||
decryptSrcFG: FormGroup;
|
||||
@ -45,7 +44,7 @@ export class SecretComponent implements WSReceiver, OnInit {
|
||||
@ViewChild('decryptStepper', { static: false }) decryptStepper: MatStepper;
|
||||
@ViewChild('encryptStepper', { static: false }) encryptStepper: MatStepper;
|
||||
|
||||
constructor(private websocketService: WebsocketService, private formBuilder: FormBuilder) {
|
||||
constructor(private websocketService: WsService, private formBuilder: FormBuilder) {
|
||||
this.websocketService.registerFunctions(this);
|
||||
}
|
||||
|
||||
@ -64,12 +63,12 @@ export class SecretComponent implements WSReceiver, OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
this.websocketService.printIfToast(message);
|
||||
} else {
|
||||
switch (message.subComponent) {
|
||||
case 'generate':
|
||||
case WsConstants.GENERATE:
|
||||
document.getElementById('GenerateOutputDiv').innerHTML = message.message;
|
||||
break;
|
||||
default:
|
||||
@ -80,21 +79,21 @@ export class SecretComponent implements WSReceiver, OnInit {
|
||||
}
|
||||
|
||||
decrypt(): void {
|
||||
const message = new WebsocketMessage(this.type, this.component, 'decrypt');
|
||||
const message = new WsMessage(this.type, this.component, WsConstants.DECRYPT);
|
||||
message.message = 'Decrypt is currently not implemented in CTL';
|
||||
this.websocketService.printIfToast(message);
|
||||
this.decryptStepper.reset();
|
||||
}
|
||||
|
||||
encrypt(): void {
|
||||
const message = new WebsocketMessage(this.type, this.component, 'encrypt');
|
||||
const message = new WsMessage(this.type, this.component, WsConstants.ENCRYPT);
|
||||
message.message = 'Encrypt is currently not implemented in CTL';
|
||||
this.websocketService.printIfToast(message);
|
||||
this.encryptStepper.reset();
|
||||
}
|
||||
|
||||
generateSecret(): void {
|
||||
const message = new WebsocketMessage(this.type, this.component, 'generate');
|
||||
const message = new WsMessage(this.type, this.component, WsConstants.GENERATE);
|
||||
Log.Debug(new LogMessage('Attempting to generate secret', this.className, message));
|
||||
this.websocketService.sendMessage(message);
|
||||
}
|
||||
|
@ -13,20 +13,20 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WebsocketService } from 'src/services/websocket/websocket.service';
|
||||
import { WSReceiver, WebsocketMessage, Authentication } from 'src/services/websocket/websocket.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsReceiver, WsMessage, Authentication, WsConstants } from 'src/services/ws/ws.models';
|
||||
|
||||
@Component({
|
||||
styleUrls: ['login.component.css'],
|
||||
templateUrl: 'login.component.html',
|
||||
})
|
||||
|
||||
export class LoginComponent implements WSReceiver, OnInit {
|
||||
export class LoginComponent implements WsReceiver, OnInit {
|
||||
className = this.constructor.name;
|
||||
type = 'ui'; // needed to have the websocket service in the constructor
|
||||
component = 'login'; // needed to have the websocket service in the constructor
|
||||
type = WsConstants.UI;
|
||||
component = WsConstants.LOGIN;
|
||||
|
||||
constructor(private websocketService: WebsocketService) { }
|
||||
constructor(private websocketService: WsService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
// bind the enter key to the submit button on the page
|
||||
@ -41,13 +41,13 @@ export class LoginComponent implements WSReceiver, OnInit {
|
||||
|
||||
// This will always throw an error but should never be called because we did not register a receiver
|
||||
// The auth guard will take care of the auth messages since it's dealing with the tokens
|
||||
receiver(message: WebsocketMessage): Promise<void> {
|
||||
receiver(message: WsMessage): Promise<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
// formSubmit sends the auth request to the backend
|
||||
public formSubmit(id, passwd): void {
|
||||
const message = new WebsocketMessage(this.type, 'auth', 'authenticate');
|
||||
const message = new WsMessage(this.type, WsConstants.AUTH, WsConstants.AUTHENTICATE);
|
||||
message.authentication = new Authentication(id, passwd);
|
||||
this.websocketService.sendMessage(message);
|
||||
}
|
||||
|
@ -13,8 +13,8 @@
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { WebsocketService } from '../../services/websocket/websocket.service';
|
||||
import { WSReceiver, WebsocketMessage } from '../../services/websocket/websocket.models';
|
||||
import { WsService } from '../../services/ws/ws.service';
|
||||
import { WsReceiver, WsMessage, WsConstants } from '../../services/ws/ws.models';
|
||||
import { Task, Progress } from './task.models';
|
||||
import { Log } from '../../services/log/log.service';
|
||||
import { LogMessage } from '../../services/log/log-message';
|
||||
@ -24,31 +24,31 @@ import { LogMessage } from '../../services/log/log-message';
|
||||
templateUrl: './task.component.html',
|
||||
styleUrls: ['./task.component.css']
|
||||
})
|
||||
export class TaskComponent implements WSReceiver {
|
||||
export class TaskComponent implements WsReceiver {
|
||||
className = this.constructor.name;
|
||||
type = 'ui';
|
||||
component = 'task';
|
||||
type = WsConstants.UI;
|
||||
component = WsConstants.TASK;
|
||||
|
||||
message: string;
|
||||
tasks: Task[] = [];
|
||||
isOpen = false;
|
||||
|
||||
constructor(private websocketService: WebsocketService) {
|
||||
constructor(private websocketService: WsService) {
|
||||
this.websocketService.registerFunctions(this);
|
||||
}
|
||||
|
||||
public async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
public async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
this.websocketService.printIfToast(message);
|
||||
} else {
|
||||
switch (message.subComponent) {
|
||||
case 'taskStart':
|
||||
case WsConstants.TASK_START:
|
||||
this.handleTaskStart(message);
|
||||
break;
|
||||
case 'taskUpdate':
|
||||
case WsConstants.TASK_UPDATE:
|
||||
this.handleTaskUpdate(message);
|
||||
break;
|
||||
case 'taskEnd':
|
||||
case WsConstants.TASK_END:
|
||||
this.handleTaskEnd(message);
|
||||
break;
|
||||
default:
|
||||
@ -58,15 +58,15 @@ export class TaskComponent implements WSReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
handleTaskStart(message: WebsocketMessage): void {
|
||||
handleTaskStart(message: WsMessage): void {
|
||||
this.addTask(message);
|
||||
const msg = new WebsocketMessage(this.type, this.component, message.subComponent);
|
||||
const msg = new WsMessage(this.type, this.component, message.subComponent);
|
||||
msg.message = `${message.name} added to Running Tasks`;
|
||||
msg.sessionID = message.sessionID;
|
||||
this.websocketService.printIfToast(msg);
|
||||
}
|
||||
|
||||
handleTaskUpdate(message: WebsocketMessage): void {
|
||||
handleTaskUpdate(message: WsMessage): void {
|
||||
const task = this.findTask(message.id);
|
||||
if (task !== null) {
|
||||
Object.assign(task.progress, message.data);
|
||||
@ -75,20 +75,20 @@ export class TaskComponent implements WSReceiver {
|
||||
task.progress.message = task.progress.errors.toString();
|
||||
}
|
||||
} else {
|
||||
const msg = new WebsocketMessage(this.type, this.component, message.subComponent);
|
||||
const msg = new WsMessage(this.type, this.component, message.subComponent);
|
||||
msg.sessionID = message.sessionID;
|
||||
msg.message = `Task with id ${message.id} not found`;
|
||||
this.websocketService.printIfToast(msg);
|
||||
}
|
||||
}
|
||||
|
||||
handleTaskEnd(message: WebsocketMessage): void {
|
||||
handleTaskEnd(message: WsMessage): void {
|
||||
const task = this.findTask(message.id);
|
||||
if (task !== null) {
|
||||
Object.assign(task.progress, message.data);
|
||||
task.running = false;
|
||||
} else {
|
||||
const msg = new WebsocketMessage(this.type, this.component, message.subComponent);
|
||||
const msg = new WsMessage(this.type, this.component, message.subComponent);
|
||||
msg.sessionID = message.sessionID;
|
||||
msg.message = `Task with id ${message.id} not found`;
|
||||
this.websocketService.printIfToast(msg);
|
||||
@ -103,7 +103,7 @@ export class TaskComponent implements WSReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
addTask(message: WebsocketMessage): void {
|
||||
addTask(message: WsMessage): void {
|
||||
const p = new Progress();
|
||||
Object.assign(p, message.data);
|
||||
|
||||
|
@ -16,14 +16,14 @@ import { Injectable } from '@angular/core';
|
||||
import { Router, CanActivate, Event as RouterEvent, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router';
|
||||
import { Log } from 'src/services/log/log.service';
|
||||
import { LogMessage } from 'src/services/log/log-message';
|
||||
import { WebsocketService } from 'src/services/websocket/websocket.service';
|
||||
import { WSReceiver, WebsocketMessage } from 'src/services/websocket/websocket.models';
|
||||
import { WsService } from 'src/services/ws/ws.service';
|
||||
import { WsReceiver, WsMessage, WsConstants } from 'src/services/ws/ws.models';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
||||
export class AuthGuard implements WSReceiver, CanActivate {
|
||||
export class AuthGuard implements WsReceiver, CanActivate {
|
||||
// static router for those who may need it, I'm looking at your app components
|
||||
public static router: Router;
|
||||
|
||||
@ -31,14 +31,14 @@ export class AuthGuard implements WSReceiver, CanActivate {
|
||||
private loading = false;
|
||||
private sendToLogin = false;
|
||||
|
||||
type = 'ui';
|
||||
component = 'auth';
|
||||
type = WsConstants.UI;
|
||||
component = WsConstants.AUTH;
|
||||
|
||||
// Called by the logout link at the top right of the page
|
||||
public static logout(): void {
|
||||
// blank out the object storage so we can't get re authenticate
|
||||
WebsocketService.token = undefined;
|
||||
WebsocketService.refreshToken = undefined;
|
||||
WsService.token = undefined;
|
||||
WsService.refreshToken = undefined;
|
||||
|
||||
// blank out the local storage so we can't get re authenticate
|
||||
localStorage.removeItem('airshipUI-token');
|
||||
@ -60,7 +60,7 @@ export class AuthGuard implements WSReceiver, CanActivate {
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private websocketService: WebsocketService, private router: Router) {
|
||||
constructor(private websocketService: WsService, private router: Router) {
|
||||
// create a static router so other components can access it if needs be
|
||||
AuthGuard.router = router;
|
||||
|
||||
@ -71,13 +71,13 @@ export class AuthGuard implements WSReceiver, CanActivate {
|
||||
});
|
||||
}
|
||||
|
||||
async receiver(message: WebsocketMessage): Promise<void> {
|
||||
if (message.hasOwnProperty('error')) {
|
||||
async receiver(message: WsMessage): Promise<void> {
|
||||
if (message.hasOwnProperty(WsConstants.ERROR)) {
|
||||
Log.Error(new LogMessage('Error received in AuthGuard', this.className, message));
|
||||
AuthGuard.logout();
|
||||
} else {
|
||||
switch (message.subComponent) {
|
||||
case 'approved':
|
||||
case WsConstants.APPROVED:
|
||||
this.setToken(message.token, false);
|
||||
Log.Debug(new LogMessage('Auth approved received', this.className, message));
|
||||
// redirect to / only when on /login otherwise leave the path where it was before the auth attempt
|
||||
@ -86,11 +86,11 @@ export class AuthGuard implements WSReceiver, CanActivate {
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
break;
|
||||
case 'denied':
|
||||
case WsConstants.DENIED:
|
||||
AuthGuard.logout();
|
||||
Log.Debug(new LogMessage('Auth denied received', this.className, message));
|
||||
break;
|
||||
case 'refresh':
|
||||
case WsConstants.REFRESH:
|
||||
this.setToken(message.refreshToken, true);
|
||||
Log.Debug(new LogMessage('Auth token refresh received', this.className, message));
|
||||
break;
|
||||
@ -159,41 +159,41 @@ export class AuthGuard implements WSReceiver, CanActivate {
|
||||
const token = JSON.parse(tokenString);
|
||||
if (token !== null) {
|
||||
if (token.hasOwnProperty('token')) {
|
||||
WebsocketService.token = token.token;
|
||||
WsService.token = token.token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the UI frontend is not the decider, the back end is. If this token is good we continue, if it's not we stop
|
||||
private validateToken(): boolean {
|
||||
if (WebsocketService.token === undefined) { this.getStoredToken(); }
|
||||
if (WsService.token === undefined) { this.getStoredToken(); }
|
||||
|
||||
// even after all this it's possible to have nothing. I started with nothing and still have most of it left
|
||||
if (WebsocketService.token !== undefined) {
|
||||
const message = new WebsocketMessage(this.type, this.component, 'validate');
|
||||
message.token = WebsocketService.token;
|
||||
if (WsService.token !== undefined) {
|
||||
const message = new WsMessage(this.type, this.component, WsConstants.VALIDATE);
|
||||
message.token = WsService.token;
|
||||
|
||||
// if we have a refresh token we also need to include that in the validity check
|
||||
if (WebsocketService.refreshToken !== undefined) {
|
||||
message.refreshToken = WebsocketService.refreshToken;
|
||||
if (WsService.refreshToken !== undefined) {
|
||||
message.refreshToken = WsService.refreshToken;
|
||||
}
|
||||
|
||||
this.websocketService.sendMessage(message);
|
||||
}
|
||||
|
||||
return WebsocketService.token !== undefined;
|
||||
return WsService.token !== undefined;
|
||||
}
|
||||
|
||||
// store the token locally so we can be authenticated between runs
|
||||
private setToken(token, isRefresh): void {
|
||||
// set the token for auth check going forward
|
||||
if (isRefresh) {
|
||||
WebsocketService.refreshToken = token;
|
||||
WsService.refreshToken = token;
|
||||
} else {
|
||||
WebsocketService.token = token;
|
||||
WsService.token = token;
|
||||
|
||||
// set the token locally to have a login till browser exits
|
||||
const json: any = { token: WebsocketService.token };
|
||||
const json: any = { token: WsService.token };
|
||||
localStorage.setItem('airshipUI-token', JSON.stringify(json));
|
||||
}
|
||||
}
|
||||
|
@ -12,15 +12,15 @@
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
import { WebsocketMessage } from '../websocket/websocket.models';
|
||||
import { WsMessage } from '../ws/ws.models';
|
||||
|
||||
export class LogMessage {
|
||||
// the holy trinity of the websocket messages, a triumvirate if you will, which is how all are routed
|
||||
message: string;
|
||||
className: string;
|
||||
logMessage: string | WebsocketMessage;
|
||||
logMessage: string | WsMessage;
|
||||
|
||||
constructor(message?: string | undefined, className?: string | undefined, logMessage?: string | WebsocketMessage | undefined) {
|
||||
constructor(message?: string | undefined, className?: string | undefined, logMessage?: string | WsMessage | undefined) {
|
||||
this.message = message;
|
||||
this.className = className;
|
||||
this.logMessage = logMessage;
|
||||
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
export interface WSReceiver {
|
||||
// the holy trinity of the websocket messages, a triumvirate if you will, which is how all are routed
|
||||
type: string;
|
||||
component: string;
|
||||
|
||||
// This is the method which will need to be implemented in the component to handle the messages
|
||||
receiver(message: WebsocketMessage): Promise<void>;
|
||||
}
|
||||
|
||||
// WebsocketMessage is the structure for the json that is used to talk to the backend
|
||||
export class WebsocketMessage {
|
||||
sessionID: string;
|
||||
type: string;
|
||||
component: string;
|
||||
subComponent: string;
|
||||
timestamp: number;
|
||||
dashboards: Dashboard[];
|
||||
error: string;
|
||||
html: string;
|
||||
name: string;
|
||||
details: string;
|
||||
id: string;
|
||||
isAuthenticated: boolean;
|
||||
message: string;
|
||||
token: string;
|
||||
refreshToken: string;
|
||||
data: JSON;
|
||||
yaml: string;
|
||||
actionType: string;
|
||||
targets: string[];
|
||||
authentication: Authentication;
|
||||
|
||||
// this constructor looks like this in case anyone decides they want just a raw message with no data predefined
|
||||
// or an easy way to specify the defaults
|
||||
constructor(type?: string | null, component?: string | null, subComponent?: string | null) {
|
||||
this.type = type;
|
||||
this.component = component;
|
||||
this.subComponent = subComponent;
|
||||
}
|
||||
}
|
||||
|
||||
// Dashboard has the urls of the links that will pop out new dashboard tabs on the left hand side
|
||||
export class Dashboard {
|
||||
name: string;
|
||||
baseURL: string;
|
||||
path: string;
|
||||
isProxied: boolean;
|
||||
}
|
||||
|
||||
// AuthMessage is used to send and auth request and hold the token if it's authenticated
|
||||
export class Authentication {
|
||||
id: string;
|
||||
password: string;
|
||||
|
||||
constructor(id?: string | null, password?: string | null) {
|
||||
this.id = id;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
140
client/src/services/ws/ws.models.ts
Executable file
140
client/src/services/ws/ws.models.ts
Executable file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
export interface WsReceiver {
|
||||
// the holy trinity of the websocket messages, a triumvirate if you will, which is how all are routed
|
||||
type: string;
|
||||
component: string;
|
||||
|
||||
// This is the method which will need to be implemented in the component to handle the messages
|
||||
receiver(message: WsMessage): Promise<void>;
|
||||
}
|
||||
|
||||
// WebsocketMessage is the structure for the json that is used to talk to the backend
|
||||
export class WsMessage {
|
||||
sessionID: string;
|
||||
type: string;
|
||||
component: string;
|
||||
subComponent: string;
|
||||
timestamp: number;
|
||||
dashboards: Dashboard[];
|
||||
error: string;
|
||||
html: string;
|
||||
name: string;
|
||||
details: string;
|
||||
id: string;
|
||||
isAuthenticated: boolean;
|
||||
message: string;
|
||||
token: string;
|
||||
refreshToken: string;
|
||||
data: JSON;
|
||||
yaml: string;
|
||||
actionType: string;
|
||||
targets: string[];
|
||||
authentication: Authentication;
|
||||
|
||||
// this constructor looks like this in case anyone decides they want just a raw message with no data predefined
|
||||
// or an easy way to specify the defaults
|
||||
constructor(type?: string | null, component?: string | null, subComponent?: string | null) {
|
||||
this.type = type;
|
||||
this.component = component;
|
||||
this.subComponent = subComponent;
|
||||
}
|
||||
}
|
||||
|
||||
export class WsConstants {
|
||||
// CTL constants
|
||||
public static readonly BAREMETAL = 'baremetal';
|
||||
public static readonly BUNDLE = 'bundle';
|
||||
public static readonly CTL = 'ctl';
|
||||
public static readonly CLUSTER = 'cluster';
|
||||
public static readonly CONFIG = 'config';
|
||||
public static readonly DECRYPT = 'decrypt';
|
||||
public static readonly DETAILS = 'details';
|
||||
public static readonly DOCUMENT = 'document';
|
||||
public static readonly DOCUMENTS = 'documents';
|
||||
public static readonly ENCRYPT = 'encrypt';
|
||||
public static readonly ERROR = 'error';
|
||||
public static readonly EXECUTOR = 'executor';
|
||||
public static readonly GET_DEFAULTS = 'getDefaults';
|
||||
public static readonly GENERATE = 'generate';
|
||||
public static readonly IMAGE = 'image';
|
||||
public static readonly INIT = 'init';
|
||||
public static readonly PHASE = 'phase';
|
||||
public static readonly PULL = 'pull';
|
||||
public static readonly RUN = 'run';
|
||||
public static readonly SECRET = 'secret';
|
||||
public static readonly VALIDATE_PHASE = 'validatePhase';
|
||||
public static readonly YAML_WRITE = 'yamlWrite';
|
||||
|
||||
public static readonly GET_DOCUMENT_BY_SELECTOR = 'getDocumentsBySelector';
|
||||
public static readonly GET_EXECUTOR_DOC = 'getExecutorDoc';
|
||||
public static readonly GET_PHASE = 'getPhase';
|
||||
public static readonly GET_PHASE_TREE = 'getPhaseTree';
|
||||
public static readonly GET_TARGET = 'getTarget';
|
||||
public static readonly GET_YAML = 'getYaml';
|
||||
|
||||
public static readonly GET_AIRSHIP_CONFIG_PATH = 'getAirshipConfigPath';
|
||||
public static readonly GET_CURRENT_CONTEXT = 'getCurrentContext';
|
||||
public static readonly GET_CONTEXTS = 'getContexts';
|
||||
public static readonly GET_ENCRYPTION_CONFIGS = 'getEncryptionConfigs';
|
||||
public static readonly GET_MANIFESTS = 'getManifests';
|
||||
public static readonly GET_MANAGEMENT_CONFIGS = 'getManagementConfigs';
|
||||
|
||||
public static readonly SET_AIRSHIP_CONFIG = 'setAirshipConfig';
|
||||
public static readonly SET_CONTEXT = 'setContext';
|
||||
public static readonly SET_MANIFEST = 'setManifest';
|
||||
public static readonly SET_MANAGEMENT_CONFIG = 'setManagementConfig';
|
||||
public static readonly SET_ENCRYPTION_CONFIG = 'setEncryptionConfig';
|
||||
public static readonly USE_CONTEXT = 'useContext';
|
||||
|
||||
// UI constants
|
||||
public static readonly ANY = 'any';
|
||||
public static readonly APPROVED = 'approved';
|
||||
public static readonly AUTH = 'auth';
|
||||
public static readonly AUTHENTICATE = 'authenticate';
|
||||
public static readonly DENIED = 'denied';
|
||||
public static readonly INITIALIZE = 'initialize';
|
||||
public static readonly KEEPALIVE = 'keepalive';
|
||||
public static readonly LOG = 'log';
|
||||
public static readonly LOGIN = 'login';
|
||||
public static readonly REFRESH = 'refresh';
|
||||
public static readonly UI = 'ui';
|
||||
public static readonly VALIDATE = 'validate';
|
||||
|
||||
public static readonly TASK = 'task';
|
||||
public static readonly TASK_END = 'taskEnd';
|
||||
public static readonly TASK_START = 'taskStart';
|
||||
public static readonly TASK_UPDATE = 'taskUpdate';
|
||||
}
|
||||
|
||||
// Dashboard has the urls of the links that will pop out new dashboard tabs on the left hand side
|
||||
export class Dashboard {
|
||||
name: string;
|
||||
baseURL: string;
|
||||
path: string;
|
||||
isProxied: boolean;
|
||||
}
|
||||
|
||||
// AuthMessage is used to send and auth request and hold the token if it's authenticated
|
||||
export class Authentication {
|
||||
id: string;
|
||||
password: string;
|
||||
|
||||
constructor(id?: string | null, password?: string | null) {
|
||||
this.id = id;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
@ -13,11 +13,11 @@
|
||||
*/
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { WebsocketService } from './websocket.service';
|
||||
import { WsService } from './ws.service';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
|
||||
describe('WebsocketService', () => {
|
||||
let service: WebsocketService;
|
||||
describe('WsService', () => {
|
||||
let service: WsService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@ -25,7 +25,7 @@ describe('WebsocketService', () => {
|
||||
ToastrModule.forRoot(),
|
||||
]
|
||||
});
|
||||
service = TestBed.inject(WebsocketService);
|
||||
service = TestBed.inject(WsService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
import { Injectable, OnDestroy } from '@angular/core';
|
||||
import { WebsocketMessage, WSReceiver, Authentication } from './websocket.models';
|
||||
import { WsMessage, WsReceiver } from './ws.models';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import 'reflect-metadata';
|
||||
|
||||
@ -21,7 +21,7 @@ import 'reflect-metadata';
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
||||
export class WebsocketService implements OnDestroy {
|
||||
export class WsService implements OnDestroy {
|
||||
// to avoid circular includes this has to go here
|
||||
public static token: string;
|
||||
public static refreshToken: string;
|
||||
@ -34,12 +34,12 @@ export class WebsocketService implements OnDestroy {
|
||||
|
||||
// functionMap is how we know where to send the direct messages
|
||||
// the structure of this map is: type -> component -> receiver
|
||||
private functionMap = new Map<string, Map<string, WSReceiver>>();
|
||||
private functionMap = new Map<string, Map<string, WsReceiver>>();
|
||||
|
||||
// messageToObject unmarshalls the incoming message into a WebsocketMessage object
|
||||
private static messageToObject(incomingMessage: string): WebsocketMessage {
|
||||
private static messageToObject(incomingMessage: string): WsMessage {
|
||||
const json = JSON.parse(incomingMessage);
|
||||
const obj = new WebsocketMessage();
|
||||
const obj = new WsMessage();
|
||||
Object.assign(obj, json);
|
||||
return obj;
|
||||
}
|
||||
@ -56,12 +56,12 @@ export class WebsocketService implements OnDestroy {
|
||||
}
|
||||
|
||||
// sendMessage will relay a WebsocketMessage to the go backend
|
||||
public async sendMessage(message: WebsocketMessage): Promise<void> {
|
||||
public async sendMessage(message: WsMessage): Promise<void> {
|
||||
try {
|
||||
message.sessionID = this.sessionID;
|
||||
message.timestamp = new Date().getTime();
|
||||
if (WebsocketService.token !== undefined) { message.token = WebsocketService.token; }
|
||||
if (WebsocketService.refreshToken !== undefined) { message.refreshToken = WebsocketService.refreshToken; }
|
||||
if (WsService.token !== undefined) { message.token = WsService.token; }
|
||||
if (WsService.refreshToken !== undefined) { message.refreshToken = WsService.refreshToken; }
|
||||
// TODO (aschiefe): determine if this debug statement is a good thing (tm)
|
||||
// Log.Debug(new LogMessage('Sending WebSocket Message', this.className, message));
|
||||
this.ws.send(JSON.stringify(message));
|
||||
@ -85,7 +85,7 @@ export class WebsocketService implements OnDestroy {
|
||||
this.ws = new WebSocket('wss://localhost:10443/ws');
|
||||
|
||||
this.ws.onmessage = (event) => {
|
||||
this.messageHandler(WebsocketService.messageToObject(event.data));
|
||||
this.messageHandler(WsService.messageToObject(event.data));
|
||||
};
|
||||
|
||||
this.ws.onerror = (event) => {
|
||||
@ -165,7 +165,7 @@ export class WebsocketService implements OnDestroy {
|
||||
}
|
||||
|
||||
// Takes the WebsocketMessage and iterates through the function map to send a directed message when it shows up
|
||||
private async messageHandler(message: WebsocketMessage): Promise<void> {
|
||||
private async messageHandler(message: WsMessage): Promise<void> {
|
||||
if (this.sessionID === undefined && message.hasOwnProperty('sessionID')) {
|
||||
this.sessionID = message.sessionID;
|
||||
}
|
||||
@ -196,26 +196,26 @@ export class WebsocketService implements OnDestroy {
|
||||
window.clearTimeout(this.keepAliveTimeout);
|
||||
window.clearInterval(this.keepAliveTimeout);
|
||||
if (this.ws !== undefined && this.ws !== null && this.ws.readyState !== this.ws.CLOSED) {
|
||||
this.sendMessage(new WebsocketMessage('ui', 'keepalive', null));
|
||||
this.sendMessage(new WsMessage('ui', 'keepalive', null));
|
||||
}
|
||||
this.keepAliveTimeout = setTimeout(() => { this.keepAlive(); }, 60000);
|
||||
}
|
||||
|
||||
// registerFunctions is a is called out of the target's constructor so it can auto populate the function map
|
||||
public registerFunctions(target: WSReceiver): void {
|
||||
public registerFunctions(target: WsReceiver): void {
|
||||
const type = target.type;
|
||||
const component = target.component;
|
||||
if (this.functionMap.hasOwnProperty(type)) {
|
||||
this.functionMap[type][component] = target;
|
||||
} else {
|
||||
const components = new Map<string, WSReceiver>();
|
||||
const components = new Map<string, WsReceiver>();
|
||||
components[component] = target;
|
||||
this.functionMap[type] = components;
|
||||
}
|
||||
}
|
||||
|
||||
// printIfToast puts up the toast popup message on the UI
|
||||
printIfToast(message: WebsocketMessage): void {
|
||||
printIfToast(message: WsMessage): void {
|
||||
if (message.error !== undefined && message.error !== null) {
|
||||
this.toastrService.error(message.error);
|
||||
} else {
|
@ -29,7 +29,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
keySize = 4096 // 4k key
|
||||
// keypair details
|
||||
keySize = 4096 // 4k key
|
||||
privateKeyType = "RSA PRIVATE KEY"
|
||||
publicKeyType = "CERTIFICATE"
|
||||
|
||||
// certificate request details
|
||||
cn = "localhost" // common name
|
||||
o = "Airship UI" // organization
|
||||
)
|
||||
|
||||
// GeneratePrivateKey will a pem encoded private key and an rsa private key object
|
||||
@ -42,7 +49,7 @@ func GeneratePrivateKey() ([]byte, *rsa.PrivateKey, error) {
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
err = pem.Encode(buf, &pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Type: privateKeyType,
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
|
||||
})
|
||||
if err != nil {
|
||||
@ -63,7 +70,7 @@ func GeneratePublicKey(privateKey *rsa.PrivateKey) ([]byte, error) {
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
err = pem.Encode(buf, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Type: publicKeyType,
|
||||
Bytes: derCert,
|
||||
})
|
||||
if err != nil {
|
||||
@ -77,8 +84,8 @@ func generateCSR() x509.Certificate {
|
||||
return x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
CommonName: "localhost",
|
||||
Organization: []string{"Airship UI"},
|
||||
CommonName: cn,
|
||||
Organization: []string{o},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(1, 0, 0),
|
||||
|
@ -17,6 +17,7 @@ package statistics
|
||||
import (
|
||||
"database/sql"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -38,6 +39,8 @@ type Transaction struct {
|
||||
}
|
||||
|
||||
var (
|
||||
doNotRecordRegex = regexp.MustCompile(`(?i)^get|^init$`) // the default gets we don't care about
|
||||
|
||||
writeMutex sync.Mutex
|
||||
db *sql.DB
|
||||
tables = []string{"baremetal", "cluster", "config", "document", "image", "phase", "secret"}
|
||||
@ -173,13 +176,7 @@ func isRecordable(request configs.WsMessage) bool {
|
||||
}
|
||||
|
||||
// don't record default get data events
|
||||
switch request.SubComponent {
|
||||
case configs.GetTarget,
|
||||
configs.GetDefaults,
|
||||
configs.GetPhaseTree,
|
||||
configs.GetPhase,
|
||||
configs.GetYaml,
|
||||
configs.GetDocumentsBySelector:
|
||||
if doNotRecordRegex.MatchString(string(request.SubComponent)) {
|
||||
recordable = false
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,12 @@ import (
|
||||
// TODO: use a private key for this instead of a phrase
|
||||
var jwtKey = []byte("airshipUI_JWT_key")
|
||||
|
||||
const (
|
||||
username = "username"
|
||||
password = "password"
|
||||
expiration = "exp"
|
||||
)
|
||||
|
||||
// The UI will either request authentication or validation, handle those situations here
|
||||
func handleAuth(_ *string, request configs.WsMessage) configs.WsMessage {
|
||||
response := configs.WsMessage{
|
||||
@ -98,7 +104,7 @@ func validateToken(request configs.WsMessage) (*string, error) {
|
||||
// extract the claim from the token
|
||||
if claim, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||
// extract the user from the claim
|
||||
if user, ok := claim["username"].(string); ok {
|
||||
if user, ok := claim[username].(string); ok {
|
||||
// test to see if we need to sent a refresh token
|
||||
go testForRefresh(claim, request)
|
||||
return &user, nil
|
||||
@ -132,9 +138,9 @@ func createToken(id string, passwd string) (*string, error) {
|
||||
|
||||
// set some claims
|
||||
claims := make(jwt.MapClaims)
|
||||
claims["username"] = id
|
||||
claims["password"] = passwd
|
||||
claims["exp"] = time.Now().Add(time.Hour * 1).Unix()
|
||||
claims[username] = id
|
||||
claims[password] = passwd
|
||||
claims[expiration] = time.Now().Add(time.Hour * 1).Unix()
|
||||
|
||||
// create the token
|
||||
jwtClaim := jwt.New(jwt.SigningMethodHS256)
|
||||
@ -149,7 +155,7 @@ func createToken(id string, passwd string) (*string, error) {
|
||||
func testForRefresh(claim jwt.MapClaims, request configs.WsMessage) {
|
||||
// for some reason the exp is stored as an float and not an int in the claim conversion
|
||||
// so we do a little dance and cast some floats to ints and everyone goes on with their lives
|
||||
if exp, ok := claim["exp"].(float64); ok {
|
||||
if exp, ok := claim[expiration].(float64); ok {
|
||||
if int64(exp) < time.Now().Add(time.Minute*15).Unix() {
|
||||
createRefreshToken(claim, request)
|
||||
}
|
||||
@ -159,7 +165,7 @@ func testForRefresh(claim jwt.MapClaims, request configs.WsMessage) {
|
||||
// createRefreshToken will create an oauth2 refresh token based on the timeout on the UI
|
||||
func createRefreshToken(claim jwt.MapClaims, request configs.WsMessage) {
|
||||
// add the new expiration to the claim
|
||||
claim["exp"] = time.Now().Add(time.Hour * 1).Unix()
|
||||
claim[expiration] = time.Now().Add(time.Hour * 1).Unix()
|
||||
|
||||
// create the token
|
||||
jwtClaim := jwt.New(jwt.SigningMethodHS256)
|
||||
|
@ -27,6 +27,14 @@ import (
|
||||
// map of proxy targets which will be used based on the request
|
||||
var proxyMap = map[string]*url.URL{}
|
||||
|
||||
const (
|
||||
host = "Host"
|
||||
xForwardHost = "X-Forwarded-Host"
|
||||
xForwardFor = "X-Forwarded-For"
|
||||
tcp = "tcp"
|
||||
localhost0 = "localhost:0"
|
||||
)
|
||||
|
||||
type transport struct {
|
||||
http.RoundTripper
|
||||
}
|
||||
@ -73,25 +81,26 @@ func handleProxy(response http.ResponseWriter, request *http.Request) {
|
||||
request.URL.Host = target.Host
|
||||
request.URL.Scheme = target.Scheme
|
||||
|
||||
host := request.Header.Get("Host")
|
||||
request.Header.Set("X-Forwarded-Host", host)
|
||||
request.Header.Set("X-Forwarded-For", host)
|
||||
host := request.Header.Get(host)
|
||||
request.Header.Set(xForwardHost, host)
|
||||
request.Header.Set(xForwardFor, host)
|
||||
|
||||
proxy.ServeHTTP(response, request)
|
||||
}
|
||||
|
||||
func getRandomPort() (string, error) {
|
||||
func getRandomPort() (*string, error) {
|
||||
// get a random port for the proxy
|
||||
listener, err := net.Listen("tcp", "localhost:0")
|
||||
listener, err := net.Listen(tcp, localhost0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// close the port so we can start the proxy
|
||||
defer listener.Close()
|
||||
|
||||
// get the string of the port
|
||||
return listener.Addr().String(), nil
|
||||
port := listener.Addr().String()
|
||||
return &port, nil
|
||||
}
|
||||
|
||||
// proxyServer will proxy dashboard connections allowing us to inject headers
|
||||
@ -124,18 +133,18 @@ func startProxies() {
|
||||
}
|
||||
|
||||
// set the target for the proxied request to the original url
|
||||
proxyMap[port] = target
|
||||
proxyMap[*port] = target
|
||||
|
||||
// set the target for the link in the ui to the proxy address
|
||||
dashboard.BaseURL = "http://" + port
|
||||
dashboard.BaseURL = "http://" + *port
|
||||
|
||||
// kick off proxy
|
||||
log.Debugf("Attempting to start proxy for %s on: %s\n", dashboard.Name, port)
|
||||
log.Debugf("Attempting to start proxy for %s on: %s\n", dashboard.Name, *port)
|
||||
|
||||
// set the dashboard from this point on to go to the proxy
|
||||
configs.UIConfig.Dashboards[index] = dashboard
|
||||
|
||||
// and away we go.........
|
||||
go proxyServer(port)
|
||||
go proxyServer(*port)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user