diff --git a/components/crud-web-apps/common/backend/kubeflow/kubeflow/crud_backend/rok/__init__.py b/components/crud-web-apps/common/backend/kubeflow/kubeflow/crud_backend/rok/__init__.py deleted file mode 100644 index c0aecdf1..00000000 --- a/components/crud-web-apps/common/backend/kubeflow/kubeflow/crud_backend/rok/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .routes import bp # noqa E402, F401 diff --git a/components/crud-web-apps/common/backend/kubeflow/kubeflow/crud_backend/rok/routes.py b/components/crud-web-apps/common/backend/kubeflow/kubeflow/crud_backend/rok/routes.py deleted file mode 100644 index 9f7fd097..00000000 --- a/components/crud-web-apps/common/backend/kubeflow/kubeflow/crud_backend/rok/routes.py +++ /dev/null @@ -1,14 +0,0 @@ -from flask import Blueprint - -from .. import api - -bp = Blueprint("rok_base_routes", __name__) - - -@bp.route("/api/rok/storageclasses") -def get_rok_storageclasses(): - """ - Return a list of k8s storage classes that are provided from Rok - """ - # TODO(kimwnasptd): Should use annotations on storage classes instead - return api.success_response("storageClasses", ["rok"]) diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/assets/browse-in-rok-blue.svg b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/assets/browse-in-rok-blue.svg deleted file mode 100644 index 50b4dfc3..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/assets/browse-in-rok-blue.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/assets/browse-in-rok-gray.svg b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/assets/browse-in-rok-gray.svg deleted file mode 100644 index 973ded99..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/assets/browse-in-rok-gray.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/assets/browse-in-rok-grey.svg b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/assets/browse-in-rok-grey.svg deleted file mode 100644 index 973ded99..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/assets/browse-in-rok-grey.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/form.module.ts b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/form.module.ts index 8943f6a4..7417feeb 100644 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/form.module.ts +++ b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/form.module.ts @@ -21,7 +21,6 @@ import { NameNamespaceInputsComponent } from './name-namespace-inputs/name-names import { NameInputComponent } from './name-namespace-inputs/name-input/name-input.component'; import { IconModule } from '../icon/icon.module'; import { PositiveNumberInputComponent } from './positive-number-input/positive-number-input.component'; -import { RokUrlInputComponent } from './rok-url-input/rok-url-input.component'; import { AdvancedOptionsComponent } from './advanced-options/advanced-options.component'; import { PopoverModule } from '../popover/popover.module'; import { SubmitBarComponent } from './submit-bar/submit-bar.component'; @@ -33,7 +32,6 @@ import { StepInfoComponent } from './step-info/step-info.component'; NameNamespaceInputsComponent, NameInputComponent, PositiveNumberInputComponent, - RokUrlInputComponent, AdvancedOptionsComponent, SubmitBarComponent, StepInfoComponent, @@ -57,7 +55,6 @@ import { StepInfoComponent } from './step-info/step-info.component'; NameNamespaceInputsComponent, NameInputComponent, PositiveNumberInputComponent, - RokUrlInputComponent, AdvancedOptionsComponent, SubmitBarComponent, StepInfoComponent, diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.html b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.html deleted file mode 100644 index 3fb30785..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.html +++ /dev/null @@ -1,23 +0,0 @@ - - Rok URL - - - {{ parseRokUrlError() }} - Restoring {{ snapshotType }} from {{ dateTime }} - diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.scss b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.scss deleted file mode 100644 index 4273372c..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.scss +++ /dev/null @@ -1,26 +0,0 @@ -.form-field-with-button { - button { - border: none; - background: none; - outline: none; - cursor: pointer; - display: flex; - align-items: center; - border-radius: 50%; - padding: 0; - border: 5px solid transparent; - } - - button:hover { - background-color: #f5f5f5; - } - - button:disabled { - background: none; - cursor: default; - } - - .mat-form-field-flex { - align-items: center; - } -} diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.spec.ts b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.spec.ts deleted file mode 100644 index 31952c73..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; - -import { RokUrlInputComponent } from './rok-url-input.component'; -import { FormControl } from '@angular/forms'; -import { FormModule } from '../form.module'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { MatSnackBarModule } from '@angular/material/snack-bar'; -import { HttpClientModule } from '@angular/common/http'; - -describe('RokUrlInputComponent', () => { - let component: RokUrlInputComponent; - let fixture: ComponentFixture; - - beforeEach( - waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [ - FormModule, - BrowserAnimationsModule, - MatSnackBarModule, - HttpClientModule, - ], - }).compileComponents(); - }), - ); - - beforeEach(() => { - fixture = TestBed.createComponent(RokUrlInputComponent); - component = fixture.componentInstance; - component.control = new FormControl(); - - fixture.detectChanges(); - }); - - it('should return a valid date using formatDate()', () => { - expect(component.formatDate('2022-08-01T10:02:00.716339+00:00')).toEqual( - '01/08/2022 - 10:02:00', - ); - }); -}); diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.ts b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.ts deleted file mode 100644 index 81575bb5..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/rok-url-input/rok-url-input.component.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { - Component, - OnInit, - Input, - HostListener, - Output, - EventEmitter, -} from '@angular/core'; -import { AbstractControl } from '@angular/forms'; -import { getRokUrlError } from '../validators'; -import { filter } from 'rxjs/operators'; -import { RokService } from '../../services/rok/rok.service'; -import { HttpHeaders } from '@angular/common/http'; -@Component({ - selector: 'lib-rok-url-input', - templateUrl: './rok-url-input.component.html', - styleUrls: ['./rok-url-input.component.scss'], -}) -export class RokUrlInputComponent implements OnInit { - @Input() control: AbstractControl; - @Input() snapshotType: string; - @Input() mode = 'group'; - @Input() create = false; - @Output() snapshotHeaders = new EventEmitter(); - - private popupChooser; - private chooserId = -1; - dateTime: string; - - constructor(public rok: RokService) {} - - ngOnInit() { - // Emit an event whenever a valid url has been detected - this.control.statusChanges - .pipe(filter(() => this.control.valid && this.control.value !== '')) - .subscribe(() => { - this.getHeaders(this.control.value); - }); - } - - // Chooser popup handlers - public openChooser() { - if (this.popupChooser && !this.popupChooser.closed) { - this.popupChooser.focus(); - return; - } - this.chooserId = Date.now(); - this.popupChooser = window.open( - `/rok/buckets?mode=${this.mode}-chooser` + - `&create=${this.create}` + - `&chooser-id=${this.chooserId}`, - 'Chooser', - `height=500,width=600,menubar=0`, - ); - } - - public parseRokUrlError() { - return getRokUrlError(this.control); - } - - @HostListener('window:message', ['$event']) - onMessage(event) { - if ( - typeof event.data === 'object' && - event.data.hasOwnProperty('chooser') && - event.data.hasOwnProperty('chooserId') && - event.data.chooserId === this.chooserId.toString() - ) { - this.control.setValue(event.data.chooser); - this.popupChooser.close(); - } - } - - getHeaders(url: string) { - this.rok.getObjectMetadata(url).subscribe(headers => { - this.snapshotHeaders.emit(headers); - this.dateTime = this.formatDate( - headers.get('x-origin-created-timestamp'), - ); - }); - } - - formatDate(inputDate: string): string { - // More info about 'en-GB' here: - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString - const myDate = new Date(inputDate).toLocaleString('en-GB', { - timeZone: 'UTC', - }); - return myDate.replace(', ', ' - '); - } -} diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/validators.ts b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/validators.ts index a8fd0272..7a989ad5 100644 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/validators.ts +++ b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/form/validators.ts @@ -10,7 +10,6 @@ import { import { Observable, of, timer, of as observableOf } from 'rxjs'; import { switchMap, map, catchError } from 'rxjs/operators'; -import { RokService } from '../services/rok/rok.service'; const dns1123LabelFmt = '[a-z0-9]([-a-z0-9]*[a-z0-9])?'; @@ -130,36 +129,3 @@ export function getNameAsyncValidators( ]), ]; } - -// Rok -export function getRokUrlError(rokUrlCtrl: AbstractControl) { - if (rokUrlCtrl.hasError('required')) { - return 'Rok URL cannot be empty'; - } - - if (rokUrlCtrl.hasError('invalidRokUrl')) { - return 'Not a valid Rok URL'; - } -} - -export function rokUrlValidator(rok: RokService): AsyncValidatorFn { - return (control: AbstractControl): Observable => { - const url = control.value; - - // Don't return error if the url is empty - if (url.length === 0) { - return of(null); - } - - // Ensure a protocol is given - // Don't fire while the user is writting - return timer(DEBOUNCE_TIME).pipe( - switchMap(() => - rok.getObjectMetadata(url, false).pipe( - map(resp => null), - catchError((msg: string) => observableOf({ invalidRokUrl: true })), - ), - ), - ); - }; -} diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/kubeflow.module.ts b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/kubeflow.module.ts index baba413f..2ad37159 100644 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/kubeflow.module.ts +++ b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/kubeflow.module.ts @@ -11,7 +11,6 @@ import { HTTP_INTERCEPTORS, HttpClientXsrfModule, } from '@angular/common/http'; -import { HeadersInterceptor } from './services/rok/injector'; import { PopoverModule } from './popover/popover.module'; import { TitleActionsToolbarModule } from './title-actions-toolbar/title-actions-toolbar.module'; import { ConditionsTableModule } from './conditions-table/conditions-table.module'; @@ -46,8 +45,5 @@ import { StatusIconModule } from './status-icon/status-icon.module'; StatusIconModule, ], imports: [CommonModule, HttpClientModule, HttpClientXsrfModule], - providers: [ - { provide: HTTP_INTERCEPTORS, useClass: HeadersInterceptor, multi: true }, - ], }) export class KubeflowModule {} diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/services/rok/injector.ts b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/services/rok/injector.ts deleted file mode 100644 index a8809e72..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/services/rok/injector.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Injectable } from '@angular/core'; -import { - HttpInterceptor, - HttpRequest, - HttpHandler, - HttpEvent, - HttpResponse, - HttpHeaders, -} from '@angular/common/http'; -import { map } from 'rxjs/operators'; -import { Observable } from 'rxjs'; - -export function forEachHttpHeader( - headers: HttpHeaders, - cb: (name: string, value: string) => void, -) { - headers.keys().forEach(name => { - // FIXME: A header name can have more than one values. We must use the - // getAll() method if we want to support more values. - const value = headers.get(name) as string; - cb(name, value); - }); -} - -@Injectable() -export class HeadersInterceptor implements HttpInterceptor { - constructor() {} - - intercept( - req: HttpRequest, - next: HttpHandler, - ): Observable> { - return next.handle(req).pipe( - map((event: HttpEvent) => { - if (!(event instanceof HttpResponse)) { - return event; - } - const evHeaders = event.headers; - const h: { [key: string]: string } = {}; - forEachHttpHeader(evHeaders, (name, value) => { - if ( - name.startsWith('x-object-meta-') || - value === 'x-container-throw-ref' - ) { - value = decodeURIComponent(value); - } - h[name] = value; - }); - return event.clone({ - headers: new HttpHeaders(h), - }); - }), - ); - } -} diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/services/rok/rok.service.ts b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/services/rok/rok.service.ts deleted file mode 100644 index 3bd9ae9c..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/services/rok/rok.service.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Injectable } from '@angular/core'; -import { BackendService } from '../backend/backend.service'; -import { SnackBarService } from '../../snack-bar/snack-bar.service'; -import { - HttpClient, - HttpHeaders, - HttpResponse, - HttpErrorResponse, -} from '@angular/common/http'; -import { map, catchError, tap } from 'rxjs/operators'; -import { Observable, throwError } from 'rxjs'; -import { RokSettings } from './types'; -import { BackendResponse } from '../backend/types'; - -@Injectable({ - providedIn: 'root', -}) -export class RokService extends BackendService { - private csrfToken = ''; - - constructor(public http: HttpClient, public dialog: SnackBarService) { - super(http, dialog); - } - - public initCSRF() { - if (this.csrfToken.length !== 0) { - return; - } - - console.log('Setting up CSRF protection for Rok'); - this.http - .get('/rok/services/settings') - .pipe( - catchError(error => this.handleError(error, true)), - map((settings: RokSettings) => { - console.log('Got back Rok settings:'); - console.log(settings); - console.log(`Using token: ${settings.static_token}`); - - if (settings.static_token === null) { - console.warn(`Using null token for CSRF protection!`); - } - - this.csrfToken = settings.static_token; - }), - ) - .subscribe(); - } - - public rokRespIsValid(resp: HttpResponse) { - const rokUrl = resp.headers.get('X-Object-Rok-URL'); - const objectUrl = resp.headers.get('X-Object-URL'); - - if (rokUrl === null || rokUrl !== objectUrl) { - throw new ErrorEvent('Bad Rok URL', { - message: `'${resp.url}' is not a valid Rok URL`, - }); - } - } - - public getObjectMetadata( - url: string, - showSnackBar = true, - ): Observable { - console.log(`Making a HEAD to '${url} to get Object Metadata`); - - return this.http - .head(url, { - headers: new HttpHeaders({ - 'X-Auth-Token': this.csrfToken, - }), - observe: 'response', - }) - .pipe( - tap(resp => this.rokRespIsValid(resp)), - catchError(error => this.handleError(error, showSnackBar)), - map((resp: HttpResponse) => { - console.log(`Metadata for object in url: ${url}`); - console.log(resp.headers); - - return resp.headers; - }), - ); - } - - public getRokManagedStorageClasses( - showSnackBar = true, - ): Observable { - // Get existing PVCs in a namespace - const url = `api/rok/storageclasses`; - - return this.http.get(url).pipe( - catchError(error => this.handleError(error, showSnackBar)), - map((data: BackendResponse) => data.storageClasses), - ); - } -} diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/services/rok/types.ts b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/services/rok/types.ts deleted file mode 100644 index e3dc1b85..00000000 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/lib/services/rok/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { BackendResponse } from '../backend/types'; - -export interface RokSettings { - static_token: string; - services_url: string; - url_prefix: string; -} diff --git a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/public-api.ts b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/public-api.ts index 674f7689..8650134c 100644 --- a/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/public-api.ts +++ b/components/crud-web-apps/common/frontend/kubeflow-common-lib/projects/kubeflow/src/public-api.ts @@ -10,7 +10,6 @@ export * from './lib/snack-bar/snack-bar.service'; export * from './lib/services/namespace.service'; export * from './lib/services/poller.service'; export * from './lib/services/backend/backend.service'; -export * from './lib/services/rok/rok.service'; export * from './lib/namespace-select/namespace-select.module'; @@ -45,14 +44,12 @@ export * from './lib/title-actions-toolbar/types'; export * from './lib/form/form.module'; export * from './lib/form/section/section.component'; -export * from './lib/form/rok-url-input/rok-url-input.component'; export * from './lib/resource-table/types'; export * from './lib/resource-table/status/types'; export * from './lib/resource-table/table/utils'; export * from './lib/snack-bar/types'; export * from './lib/services/backend/types'; -export * from './lib/services/rok/types'; export * from './lib/confirm-dialog/types'; export * from './lib/polling/exponential-backoff'; export * from './lib/form/validators';