Skip to content

Commit

Permalink
Fix exec (#4124)
Browse files Browse the repository at this point in the history
* Fix exec

* Remove debug logs
  • Loading branch information
Sebastian Florek authored and k8s-ci-robot committed Jul 25, 2019
1 parent 1e88abc commit 6ac204a
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 40 deletions.
15 changes: 15 additions & 0 deletions src/app/frontend/common/services/resource/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export enum Resource {
service = 'service',
event = 'event',
container = 'container',
}

export enum Utility {
shell = 'shell',
}

Expand All @@ -62,8 +65,20 @@ class ResourceEndpoint {
}
}

class UtilityEndpoint {
constructor(private readonly utility_: Utility) {}

shell(namespace: string, resourceName: string): string {
return `${baseHref}/${Resource.pod}/${namespace}/${resourceName}/${this.utility_}`;
}
}

export class EndpointManager {
static resource(resource: Resource, namespaced?: boolean): ResourceEndpoint {
return new ResourceEndpoint(resource, namespaced);
}

static utility(utility: Utility): UtilityEndpoint {
return new UtilityEndpoint(utility);
}
}
3 changes: 2 additions & 1 deletion src/app/frontend/common/services/resource/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import {NamespacedResourceService, ResourceService} from './resource';
import {UtilityService} from './utility';

@NgModule({
imports: [RouterModule],
providers: [ResourceService, NamespacedResourceService],
providers: [ResourceService, NamespacedResourceService, UtilityService],
})
export class ResourceModule {}
5 changes: 3 additions & 2 deletions src/app/frontend/common/services/resource/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import {HttpClient, HttpParams} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {merge, timer} from 'rxjs';
import {timer} from 'rxjs';
import {Observable} from 'rxjs/Observable';
import {publishReplay, refCount, switchMap, switchMapTo} from 'rxjs/operators';

Expand All @@ -25,7 +25,8 @@ import {NamespaceService} from '../global/namespace';
@Injectable()
export class ResourceService<T> extends ResourceBase<T> {
/**
* We need to provide HttpClient here since the base is not annotated with @Injectable
* We need to provide HttpClient here since the base is not annotated with
* @Injectable
*/
constructor(readonly http: HttpClient, private readonly settings_: GlobalSettingsService) {
super(http);
Expand Down
31 changes: 31 additions & 0 deletions src/app/frontend/common/services/resource/utility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2017 The Kubernetes Authors.
//
// 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.

import {HttpClient, HttpParams} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';

import {ResourceBase} from '../../resources/resource';
import {NamespaceService} from '../global/namespace';

@Injectable()
export class UtilityService<T> extends ResourceBase<T> {
constructor(readonly http: HttpClient, private readonly namespace_: NamespaceService) {
super(http);
}

shell(endpoint: string, params?: HttpParams): Observable<T> {
return this.http.get<T>(endpoint, {params});
}
}
91 changes: 54 additions & 37 deletions src/app/frontend/shell/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
OnDestroy,
ViewChild,
} from '@angular/core';
Expand All @@ -31,11 +32,13 @@ import {
} from '@api/backendapi';
import {debounce} from 'lodash';
import {ReplaySubject, Subject, Subscription} from 'rxjs';
import {takeUntil} from 'rxjs/operators';
import {Terminal} from 'xterm';
import {fit} from 'xterm/lib/addons/fit/fit';

import {EndpointManager, Resource} from '../common/services/resource/endpoint';
import {EndpointManager, Resource, Utility} from '../common/services/resource/endpoint';
import {NamespacedResourceService} from '../common/services/resource/resource';
import {UtilityService} from '../common/services/resource/utility';

// tslint:disable-next-line:no-any
declare let SockJS: any;
Expand All @@ -52,7 +55,7 @@ export class ShellComponent implements AfterViewInit, OnDestroy {
selectedContainer: string;
containers: string[];

private namespace_: string;
private readonly namespace_: string;
private connecting_: boolean;
private connectionClosed_: boolean;
private conn_: WebSocket;
Expand All @@ -61,42 +64,56 @@ export class ShellComponent implements AfterViewInit, OnDestroy {
private connSubject_ = new ReplaySubject<ShellFrame>(100);
private incommingMessage$_ = new Subject<ShellFrame>();
private readonly endpoint_ = EndpointManager.resource(Resource.pod, true);
private readonly subscriptions_: Subscription[] = [];
private readonly unsubscribe_ = new Subject<void>();
private readonly keyEvent$_ = new ReplaySubject<KeyboardEvent>(2);

constructor(
private readonly containers_: NamespacedResourceService<PodContainerList>,
private readonly terminal_: NamespacedResourceService<TerminalResponse>,
private readonly utility_: UtilityService<TerminalResponse>,
private readonly activatedRoute_: ActivatedRoute,
private readonly matSnackBar_: MatSnackBar,
private readonly cdr_: ChangeDetectorRef,
private readonly _router: Router,
) {
this.namespace_ = this.activatedRoute_.snapshot.params.resourceNamespace;
this.podName = this.activatedRoute_.snapshot.params.resourceName;
this.selectedContainer = this.activatedRoute_.snapshot.params.containerName;

const containersEndpoint = this.endpoint_.child(
this.podName,
Resource.container,
this.namespace_,
);
this.containers_
.get(containersEndpoint)
.pipe(takeUntil(this.unsubscribe_))
.subscribe(containerList => {
this.containers = containerList.containers;
if (this.containers.length > 0 && !this.selectedContainer) {
this.onPodContainerChange(this.containers[0]);
}
});
}

ngAfterViewInit(): void {
this.activatedRoute_.paramMap.pipe(takeUntil(this.unsubscribe_)).subscribe(paramMap => {
const container = paramMap.get('containerName');

this.containers_.get(containersEndpoint).subscribe(containerList => {
this.containers = containerList.containers;
if (this.containers.length > 0 && !this.selectedContainer) {
this.selectedContainer = this.containers[0];
if (this.conn_ && this.connected_) {
this.disconnect();
}

this.setupConnection();
if (container) {
this.selectedContainer = container;
this.setupConnection();
this.initTerm();
}
});
}

ngAfterViewInit(): void {
this.initTerm();
}

ngOnDestroy(): void {
this.unsubscribe_.next();
this.unsubscribe_.complete();

if (this.conn_) {
this.conn_.close();
}
Expand All @@ -105,10 +122,6 @@ export class ShellComponent implements AfterViewInit, OnDestroy {
this.connSubject_.complete();
}

for (const sub of this.subscriptions_) {
sub.unsubscribe();
}

if (this.term) {
this.term.dispose();
}
Expand All @@ -117,6 +130,12 @@ export class ShellComponent implements AfterViewInit, OnDestroy {
}

onPodContainerChange(podContainer: string): void {
this._router.navigate([`/shell/${this.namespace_}/${this.podName}/${podContainer}`], {
queryParamsHandling: 'preserve',
});
}

disconnect(): void {
if (this.conn_) {
this.conn_.close();
}
Expand All @@ -132,18 +151,18 @@ export class ShellComponent implements AfterViewInit, OnDestroy {

this.incommingMessage$_.complete();
this.incommingMessage$_ = new Subject<ShellFrame>();

this.selectedContainer = podContainer;

this._router.navigate([`/shell/${this.namespace_}/${this.podName}/${this.selectedContainer}`], {
queryParamsHandling: 'preserve',
});

this.setupConnection();
this.initTerm();
}

initTerm(): void {
if (this.connSubject_) {
this.connSubject_.complete();
this.connSubject_ = new ReplaySubject<ShellFrame>(100);
}

if (this.term) {
this.term.dispose();
}

this.term = new Terminal({
fontSize: 14,
fontFamily: 'Consolas, "Courier New", monospace',
Expand All @@ -159,11 +178,9 @@ export class ShellComponent implements AfterViewInit, OnDestroy {
this.debouncedFit_();
window.addEventListener('resize', () => this.debouncedFit_());

this.subscriptions_.push(
this.connSubject_.subscribe(frame => {
this.handleConnectionMessage(frame);
}),
);
this.connSubject_.pipe(takeUntil(this.unsubscribe_)).subscribe(frame => {
this.handleConnectionMessage(frame);
});

this.term.on('data', this.onTerminalSendString.bind(this));
this.term.on('resize', this.onTerminalResize.bind(this));
Expand All @@ -182,11 +199,11 @@ export class ShellComponent implements AfterViewInit, OnDestroy {
this.connecting_ = true;
this.connectionClosed_ = false;

const terminalSessionUrl =
this.endpoint_.child(this.podName, Resource.shell, this.namespace_) +
'/' +
this.selectedContainer;
const {id} = await this.terminal_.get(terminalSessionUrl).toPromise();
const terminalSessionUrl = `${EndpointManager.utility(Utility.shell).shell(
this.namespace_,
this.podName,
)}/${this.selectedContainer}`;
const {id} = await this.utility_.shell(terminalSessionUrl).toPromise();

this.conn_ = new SockJS(`api/sockjs?${id}`);
this.conn_.onopen = this.onConnectionOpen.bind(this, id);
Expand Down

0 comments on commit 6ac204a

Please sign in to comment.