diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 06109895..bc7d2b35 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -9,10 +9,12 @@ import { AuthGuard } from './auth.guard'; import { StepComponent } from './scenario/step.component'; import { PrintableComponent } from './printable/printable.component'; import { GuacTerminalComponent } from './scenario/guacTerminal.component'; +import { WebsocketTestComponent } from './websocket-test/websockettest.component'; const routes: Routes = [ { path: '', redirectTo: '/app/home', pathMatch: 'full' }, { path: 'login', component: LoginComponent }, + { path: 'test/:url', component: WebsocketTestComponent }, { path: 'add/:accesscode', component: AppComponent, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 1d10825e..4ac9b527 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -48,6 +48,7 @@ import { VerificationService } from './services/verification.service'; import { TaskProgressComponent } from './scenario/task-progress/task-progress.component'; import { TaskModalComponent } from './scenario/task-modal/task-modal.component'; import { SingleTaskVerificationMarkdownComponent } from './hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component'; +import { WebsocketTestComponent } from './websocket-test/websockettest.component'; import '@cds/core/icon/register.js'; import { ClarityIcons, @@ -171,6 +172,7 @@ export function jwtOptionsFactory() { TaskProgressComponent, TaskModalComponent, SingleTaskVerificationMarkdownComponent, + WebsocketTestComponent, ], imports: [ BrowserModule, diff --git a/src/app/websocket-test/websockettest.component.css b/src/app/websocket-test/websockettest.component.css new file mode 100644 index 00000000..a7835876 --- /dev/null +++ b/src/app/websocket-test/websockettest.component.css @@ -0,0 +1,8 @@ +as-split-area { + margin-left: 10px; +} + +.success { + color: green; + font-weight: bold; +} diff --git a/src/app/websocket-test/websockettest.component.html b/src/app/websocket-test/websockettest.component.html new file mode 100644 index 00000000..d7f3361a --- /dev/null +++ b/src/app/websocket-test/websockettest.component.html @@ -0,0 +1,43 @@ +
+
+ +
+ + + +

Websocket Tester

+ This page is dedicated to test if the websocket for the shell proxy is + reachable. If it is reachable you should be able to see +
    +
  1. /healthz endpoint responding with 200
  2. +
  3. Websocket being opened
  4. +
  5. Client sending a ping
  6. +
  7. Websocket responding with pong
  8. +
+

Troubleshooting

+ If the /healthz endopoint is not responding you should check if the shell + proxy is up and running. Also verify that {{ endpoint }} is the correct + URL to the proxy. If the endpoint responds with 200 but the websocket is + not being opened, you should verify that no firewall is in place that + disallows the usage of websockets for {{ endpoint }} +
+ + +

Testing {{ target }}:

+ + +
+ Check successfully completed and websocket reachable. + +
+
+
+
diff --git a/src/app/websocket-test/websockettest.component.ts b/src/app/websocket-test/websockettest.component.ts new file mode 100644 index 00000000..5ed04870 --- /dev/null +++ b/src/app/websocket-test/websockettest.component.ts @@ -0,0 +1,78 @@ +import { HttpClient } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { HfMarkdownRenderContext } from '../hf-markdown/hf-markdown.component'; +import { AppConfigService } from '../app-config.service'; + +@Component({ + selector: 'app-websockettest', + templateUrl: './websockettest.component.html', + styleUrls: ['./websockettest.component.css'], +}) +export class WebsocketTestComponent implements OnInit { + target: string; + wsEndpoint: string; + endpoint: string; + + completed: boolean; + + mermaidString = 'sequenceDiagram'; + markdownString = ''; + mdContext: HfMarkdownRenderContext = { vmInfo: {}, session: '' }; + + private Config = this.config.getConfig(); + public title = this.Config.title || "Rancher's Hobby Farm"; + + constructor( + private config: AppConfigService, + private route: ActivatedRoute, + private http: HttpClient, + ) {} + ngOnInit(): void { + this.target = this.route.snapshot.params['url']; + this.endpoint = 'https://' + this.target + '/shell/healthz'; + this.wsEndpoint = 'wss://' + this.target + '/shell/websocketTest'; + this.testConnection(); + } + + testConnection() { + this.addMermaidString('you', this.target, '/shell/healthz'); + this.http.get(this.endpoint).subscribe({ + next: () => { + this.addMermaidString(this.target, 'you', '200, OK'); + this.testWSConnection(); + }, + error: (msg) => { + console.log(msg); + this.addMermaidString(this.target, 'you', msg.code); + }, + }); + } + + testWSConnection() { + this.addMermaidString('you', this.target, 'open websocket', '+'); + const socket = new WebSocket(this.wsEndpoint); + socket.onmessage = (event) => { + if (event.data == 'pong') { + this.addMermaidString(this.target, 'you', 'pong', '-'); + this.completed = true; + } + }; + + socket.onopen = () => { + this.addMermaidString(this.target, 'you', 'websocket opened'); + socket.send('ping'); + this.addMermaidString('you', this.target, 'ping'); + }; + } + + addMermaidString( + from: string, + to: string, + content: string, + opChar: string = '', + ) { + this.mermaidString += '\n ' + from + '->>' + opChar + to + ': ' + content; + this.markdownString = '```mermaid\n' + this.mermaidString + '\n```'; + } +}