mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-26 20:26:13 +01:00
Refactor gc and gi history page (#14728)
Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
2ffa6580fa
commit
705cb5b55d
@ -3,10 +3,7 @@ import { RouterModule, Routes } from "@angular/router";
|
|||||||
import { GcPageComponent } from "./gc-page.component";
|
import { GcPageComponent } from "./gc-page.component";
|
||||||
import { GcComponent } from "./gc/gc.component";
|
import { GcComponent } from "./gc/gc.component";
|
||||||
import { GcHistoryComponent } from "./gc/gc-history/gc-history.component";
|
import { GcHistoryComponent } from "./gc/gc-history/gc-history.component";
|
||||||
import { GcRepoService } from "./gc/gc.service";
|
|
||||||
import { SharedModule } from "../../../shared/shared.module";
|
import { SharedModule } from "../../../shared/shared.module";
|
||||||
import { GcApiDefaultRepository, GcApiRepository } from "./gc/gc.api.repository";
|
|
||||||
import { GcViewModelFactory } from "./gc/gc.viewmodel.factory";
|
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -24,10 +21,5 @@ const routes: Routes = [
|
|||||||
GcComponent,
|
GcComponent,
|
||||||
GcHistoryComponent
|
GcHistoryComponent
|
||||||
],
|
],
|
||||||
providers: [
|
|
||||||
GcRepoService,
|
|
||||||
{provide: GcApiRepository, useClass: GcApiDefaultRepository },
|
|
||||||
GcViewModelFactory
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
export class GcModule {}
|
export class GcModule {}
|
||||||
|
@ -1,30 +1,35 @@
|
|||||||
<h5 class="history-header" id="history-header">{{'GC.JOB_HISTORY' | translate}}</h5>
|
<h5 class="history-header" id="history-header">{{'GC.JOB_HISTORY' | translate}}</h5>
|
||||||
<span class="refresh-btn" (click)="getJobs()">
|
<span class="refresh-btn" (click)="refresh()">
|
||||||
<clr-icon shape="refresh"></clr-icon>
|
<clr-icon shape="refresh"></clr-icon>
|
||||||
</span>
|
</span>
|
||||||
<clr-datagrid [clrDgLoading]="loading">
|
<clr-datagrid [clrDgLoading]="loading" (clrDgRefresh)="getJobs($event)">
|
||||||
<clr-dg-column>{{'GC.JOB_ID' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'id'">{{'GC.JOB_ID' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'GC.TRIGGER_TYPE' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'GC.TRIGGER_TYPE' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'TAG_RETENTION.DRY_RUN' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'TAG_RETENTION.DRY_RUN' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'STATUS' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'STATUS' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'CREATION_TIME' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'CREATION_TIME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'UPDATE_TIME' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgSortBy]="'update_time'">{{'UPDATE_TIME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column>{{'LOGS' | translate}}</clr-dg-column>
|
<clr-dg-column>{{'LOGS' | translate}}</clr-dg-column>
|
||||||
<clr-dg-row *clrDgItems="let job of jobs" [clrDgItem]='job'>
|
<clr-dg-row *ngFor="let job of jobs" [clrDgItem]='job'>
|
||||||
<clr-dg-cell>{{job.id }}</clr-dg-cell>
|
<clr-dg-cell>{{job.id }}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{(job.type ? 'SCHEDULE.'+ job.type.toUpperCase() : '') | translate }}</clr-dg-cell>
|
<clr-dg-cell>{{(job.schedule?.type ? 'SCHEDULE.' + job.schedule?.type.toUpperCase() : '') | translate }}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{isDryRun(job?.parameters) | translate}}</clr-dg-cell>
|
<clr-dg-cell>{{isDryRun(job?.job_parameters) | translate}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{job.status.toUpperCase() | translate}}</clr-dg-cell>
|
<clr-dg-cell>{{job.job_status.toUpperCase() | translate}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{job.createTime | harborDatetime:'medium'}}</clr-dg-cell>
|
<clr-dg-cell>{{job.creation_time | harborDatetime:'medium'}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{job.updateTime | harborDatetime:'medium'}}</clr-dg-cell>
|
<clr-dg-cell>{{job.update_time | harborDatetime:'medium'}}</clr-dg-cell>
|
||||||
<clr-dg-cell>
|
<clr-dg-cell>
|
||||||
<a *ngIf="job.status.toLowerCase() === 'success' || job.status.toLowerCase() === 'error'" target="_blank" [href]="getLogLink(job.id)"><clr-icon shape="list"></clr-icon></a>
|
<a *ngIf="job.job_status.toLowerCase() === 'success' || job.job_status.toLowerCase() === 'error'" target="_blank"
|
||||||
</clr-dg-cell>
|
[href]="getLogLink(job.id)">
|
||||||
</clr-dg-row>
|
<clr-icon shape="list"></clr-icon>
|
||||||
<clr-dg-footer>
|
</a>
|
||||||
<clr-dg-pagination [clrDgPageSize]="15">
|
</clr-dg-cell>
|
||||||
<clr-dg-page-size [clrPageSizeOptions]="[15,25,50]">{{"PAGINATION.PAGE_SIZE" | translate}}</clr-dg-page-size>
|
</clr-dg-row>
|
||||||
{{'GC.LATEST_JOBS' | translate :{param: jobs.length} }}
|
<clr-dg-footer>
|
||||||
</clr-dg-pagination>
|
<clr-dg-pagination #pagination [clrDgPageSize]="pageSize" [(clrDgPage)]="page" [clrDgTotalItems]="total">
|
||||||
</clr-dg-footer>
|
<clr-dg-page-size [clrPageSizeOptions]="[15,25,50]">{{"PAGINATION.PAGE_SIZE" | translate}}</clr-dg-page-size>
|
||||||
|
<span *ngIf="total">{{pagination.firstItem + 1}}
|
||||||
|
- {{pagination.lastItem + 1}} {{'DESTINATION.OF' | translate}}</span>
|
||||||
|
{{total}} {{'DESTINATION.ITEMS' | translate}}
|
||||||
|
</clr-dg-pagination>
|
||||||
|
</clr-dg-footer>
|
||||||
</clr-datagrid>
|
</clr-datagrid>
|
||||||
|
@ -1,100 +1,99 @@
|
|||||||
import {
|
import {
|
||||||
ComponentFixture,
|
ComponentFixture,
|
||||||
ComponentFixtureAutoDetect,
|
ComponentFixtureAutoDetect, fakeAsync,
|
||||||
TestBed,
|
TestBed, tick,
|
||||||
waitForAsync
|
|
||||||
} from '@angular/core/testing';
|
} from '@angular/core/testing';
|
||||||
import { GcRepoService } from "../gc.service";
|
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { GcViewModelFactory } from "../gc.viewmodel.factory";
|
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|
||||||
import { ErrorHandler } from '../../../../../shared/units/error-handler';
|
|
||||||
import { GcHistoryComponent } from './gc-history.component';
|
import { GcHistoryComponent } from './gc-history.component';
|
||||||
import { GcJobData } from "../gcLog";
|
|
||||||
import { SharedTestingModule } from "../../../../../shared/shared.module";
|
import { SharedTestingModule } from "../../../../../shared/shared.module";
|
||||||
|
import { GCHistory } from "../../../../../../../ng-swagger-gen/models/gchistory";
|
||||||
|
import { HttpHeaders, HttpResponse } from "@angular/common/http";
|
||||||
|
import { Registry } from "../../../../../../../ng-swagger-gen/models/registry";
|
||||||
|
import { GcService } from "../../../../../../../ng-swagger-gen/services/gc.service";
|
||||||
|
import { CURRENT_BASE_HREF } from "../../../../../shared/units/utils";
|
||||||
|
import { delay } from "rxjs/operators";
|
||||||
|
|
||||||
describe('GcHistoryComponent', () => {
|
describe('GcHistoryComponent', () => {
|
||||||
let component: GcHistoryComponent;
|
let component: GcHistoryComponent;
|
||||||
let fixture: ComponentFixture<GcHistoryComponent>;
|
let fixture: ComponentFixture<GcHistoryComponent>;
|
||||||
const mockJobs: GcJobData[] = [
|
const mockJobs: GCHistory[] = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
job_name: 'test',
|
job_name: 'test',
|
||||||
job_kind: 'manual',
|
job_kind: 'manual',
|
||||||
schedule: null,
|
schedule: null,
|
||||||
job_status: 'pending',
|
job_status: 'pending',
|
||||||
job_parameters: '{"dry_run":true}',
|
job_parameters: '{"dry_run":true}',
|
||||||
job_uuid: 'abc',
|
creation_time: null,
|
||||||
creation_time: null,
|
update_time: null,
|
||||||
update_time: null,
|
},
|
||||||
delete: false
|
{
|
||||||
},
|
id: 2,
|
||||||
{
|
job_name: 'test',
|
||||||
id: 2,
|
job_kind: 'manual',
|
||||||
job_name: 'test',
|
schedule: null,
|
||||||
job_kind: 'manual',
|
job_status: 'finished',
|
||||||
schedule: null,
|
job_parameters: '{"dry_run":true}',
|
||||||
job_status: 'finished',
|
creation_time: null,
|
||||||
job_parameters: '{"dry_run":true}',
|
update_time: null,
|
||||||
job_uuid: 'bcd',
|
}
|
||||||
creation_time: null,
|
];
|
||||||
update_time: null,
|
const fakedGcService = {
|
||||||
delete: false
|
count: 0,
|
||||||
}
|
getGCHistoryResponse() {
|
||||||
];
|
if (this.count === 0) {
|
||||||
let fakeGcRepoService = {
|
this.count += 1;
|
||||||
count: 0,
|
const response: HttpResponse<Array<Registry>> = new HttpResponse<Array<Registry>>({
|
||||||
getJobs() {
|
headers: new HttpHeaders({'x-total-count': [mockJobs[0]].length.toString()}),
|
||||||
if (this.count === 0) {
|
body: [mockJobs[0]]
|
||||||
this.count += 1;
|
|
||||||
return of([mockJobs[0]]);
|
|
||||||
} else {
|
|
||||||
this.count += 1;
|
|
||||||
return of([mockJobs[1]]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getLogLink() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const fakeGcViewModelFactory = new GcViewModelFactory();
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [GcHistoryComponent],
|
|
||||||
imports: [
|
|
||||||
SharedTestingModule,
|
|
||||||
TranslateModule.forRoot()
|
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
ErrorHandler,
|
|
||||||
TranslateService,
|
|
||||||
GcViewModelFactory,
|
|
||||||
{ provide: GcRepoService, useValue: fakeGcRepoService },
|
|
||||||
{ provide: GcViewModelFactory, useValue: fakeGcViewModelFactory },
|
|
||||||
// open auto detect
|
|
||||||
{ provide: ComponentFixtureAutoDetect, useValue: true }
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
return of(response).pipe(delay(0));
|
||||||
|
} else {
|
||||||
|
this.count += 1;
|
||||||
|
const response: HttpResponse<Array<Registry>> = new HttpResponse<Array<Registry>>({
|
||||||
|
headers: new HttpHeaders({'x-total-count': [mockJobs[1]].length.toString()}),
|
||||||
|
body: [mockJobs[1]]
|
||||||
|
});
|
||||||
|
return of(response).pipe(delay(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [GcHistoryComponent],
|
||||||
|
imports: [
|
||||||
|
SharedTestingModule,
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{provide: GcService, useValue: fakedGcService},
|
||||||
|
// open auto detect
|
||||||
|
{provide: ComponentFixtureAutoDetect, useValue: true}
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(GcHistoryComponent);
|
fixture = TestBed.createComponent(GcHistoryComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
if (component && component.timerDelay) {
|
||||||
|
component.timerDelay.unsubscribe();
|
||||||
|
component.timerDelay = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('should retry getting jobs', fakeAsync(() => {
|
||||||
|
tick(10000);
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(component.jobs[0].job_status).toEqual('finished');
|
||||||
});
|
});
|
||||||
afterEach(() => {
|
}));
|
||||||
if (component && component.timerDelay) {
|
it('should return right log link', () => {
|
||||||
component.timerDelay.unsubscribe();
|
expect(component.getLogLink('1')).toEqual(`${CURRENT_BASE_HREF}/system/gc/1/log`);
|
||||||
component.timerDelay = null;
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
it('should retry getting jobs', waitForAsync(() => {
|
|
||||||
fixture.detectChanges();
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
expect(component.jobs[1].status).toEqual('finished');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
|
@ -1,64 +1,103 @@
|
|||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
import { GcRepoService } from "../gc.service";
|
|
||||||
import { GcJobViewModel } from "../gcLog";
|
|
||||||
import { GcViewModelFactory } from "../gc.viewmodel.factory";
|
|
||||||
import { ErrorHandler } from "../../../../../shared/units/error-handler";
|
import { ErrorHandler } from "../../../../../shared/units/error-handler";
|
||||||
import { Subscription, timer } from "rxjs";
|
import { Subscription, timer } from "rxjs";
|
||||||
import { REFRESH_TIME_DIFFERENCE } from '../../../../../shared/entities/shared.const';
|
import { REFRESH_TIME_DIFFERENCE } from '../../../../../shared/entities/shared.const';
|
||||||
|
import { GcService } from "../../../../../../../ng-swagger-gen/services/gc.service";
|
||||||
|
import { CURRENT_BASE_HREF, DEFAULT_PAGE_SIZE, getSortingString } from "../../../../../shared/units/utils";
|
||||||
|
import { ClrDatagridStateInterface } from "@clr/angular";
|
||||||
|
import { finalize } from "rxjs/operators";
|
||||||
|
import { GCHistory } from "../../../../../../../ng-swagger-gen/models/gchistory";
|
||||||
|
|
||||||
const JOB_STATUS = {
|
const JOB_STATUS = {
|
||||||
PENDING: "pending",
|
PENDING: "pending",
|
||||||
RUNNING: "running"
|
RUNNING: "running"
|
||||||
};
|
};
|
||||||
const YES: string = 'TAG_RETENTION.YES';
|
const YES: string = 'TAG_RETENTION.YES';
|
||||||
const NO: string = 'TAG_RETENTION.NO';
|
const NO: string = 'TAG_RETENTION.NO';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'gc-history',
|
selector: 'gc-history',
|
||||||
templateUrl: './gc-history.component.html',
|
templateUrl: './gc-history.component.html',
|
||||||
styleUrls: ['./gc-history.component.scss']
|
styleUrls: ['./gc-history.component.scss']
|
||||||
})
|
})
|
||||||
export class GcHistoryComponent implements OnInit, OnDestroy {
|
export class GcHistoryComponent implements OnInit, OnDestroy {
|
||||||
jobs: Array<GcJobViewModel> = [];
|
jobs: Array<GCHistory> = [];
|
||||||
loading: boolean;
|
loading: boolean = true;
|
||||||
timerDelay: Subscription;
|
timerDelay: Subscription;
|
||||||
|
pageSize: number = DEFAULT_PAGE_SIZE;
|
||||||
|
page: number = 1;
|
||||||
|
total: number = 0;
|
||||||
|
state: ClrDatagridStateInterface;
|
||||||
constructor(
|
constructor(
|
||||||
private gcRepoService: GcRepoService,
|
private gcService: GcService,
|
||||||
private gcViewModelFactory: GcViewModelFactory,
|
|
||||||
private errorHandler: ErrorHandler
|
private errorHandler: ErrorHandler
|
||||||
) {}
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
this.page = 1;
|
||||||
|
this.total = 0;
|
||||||
this.getJobs();
|
this.getJobs();
|
||||||
}
|
}
|
||||||
|
|
||||||
getJobs() {
|
getJobs(state?: ClrDatagridStateInterface) {
|
||||||
|
if (state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
if (state && state.page) {
|
||||||
|
this.pageSize = state.page.size;
|
||||||
|
}
|
||||||
|
let q: string;
|
||||||
|
if (state && state.filters && state.filters.length) {
|
||||||
|
q = encodeURIComponent(`${state.filters[0].property}=~${state.filters[0].value}`);
|
||||||
|
}
|
||||||
|
let sort: string;
|
||||||
|
if (state && state.sort && state.sort.by) {
|
||||||
|
sort = getSortingString(state);
|
||||||
|
}
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.gcRepoService.getJobs().subscribe(jobs => {
|
this.gcService.getGCHistoryResponse({
|
||||||
this.jobs = this.gcViewModelFactory.createJobViewModel(jobs);
|
page: this.page,
|
||||||
this.loading = false;
|
pageSize: this.pageSize,
|
||||||
// to avoid some jobs not finished.
|
q: q,
|
||||||
if (!this.timerDelay) {
|
sort: sort
|
||||||
this.timerDelay = timer(REFRESH_TIME_DIFFERENCE, REFRESH_TIME_DIFFERENCE).subscribe(() => {
|
}).pipe(finalize(() => this.loading = false))
|
||||||
let count: number = 0;
|
.subscribe(res => {
|
||||||
this.jobs.forEach(job => {
|
// Get total count
|
||||||
if (
|
if (res.headers) {
|
||||||
job['status'] === JOB_STATUS.PENDING ||
|
const xHeader: string = res.headers.get("X-Total-Count");
|
||||||
job['status'] === JOB_STATUS.RUNNING
|
if (xHeader) {
|
||||||
) {
|
this.total = parseInt(xHeader, 0);
|
||||||
count++;
|
}
|
||||||
|
this.jobs = res.body;
|
||||||
|
}
|
||||||
|
// to avoid some jobs not finished.
|
||||||
|
if (!this.timerDelay) {
|
||||||
|
this.timerDelay = timer(REFRESH_TIME_DIFFERENCE, REFRESH_TIME_DIFFERENCE).subscribe(() => {
|
||||||
|
let count: number = 0;
|
||||||
|
this.jobs.forEach(job => {
|
||||||
|
if (
|
||||||
|
job.job_status === JOB_STATUS.PENDING ||
|
||||||
|
job.job_status === JOB_STATUS.RUNNING
|
||||||
|
) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (count > 0) {
|
||||||
|
this.getJobs(this.state);
|
||||||
|
} else {
|
||||||
|
this.timerDelay.unsubscribe();
|
||||||
|
this.timerDelay = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (count > 0) {
|
}
|
||||||
this.getJobs();
|
}, error => {
|
||||||
} else {
|
|
||||||
this.timerDelay.unsubscribe();
|
|
||||||
this.timerDelay = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, error => {
|
|
||||||
this.errorHandler.error(error);
|
this.errorHandler.error(error);
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
isDryRun(param: string): string {
|
isDryRun(param: string): string {
|
||||||
@ -78,7 +117,7 @@ export class GcHistoryComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getLogLink(id): string {
|
getLogLink(id): string {
|
||||||
return this.gcRepoService.getLogLink(id);
|
return `${CURRENT_BASE_HREF}/system/gc/${id}/log`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { HttpClient } from '@angular/common/http';
|
|
||||||
import { throwError as observableThrowError, Observable } from 'rxjs';
|
|
||||||
import { catchError } from 'rxjs/operators';
|
|
||||||
import { CURRENT_BASE_HREF } from "../../../../shared/units/utils";
|
|
||||||
|
|
||||||
export abstract class GcApiRepository {
|
|
||||||
abstract postSchedule(param): Observable<any>;
|
|
||||||
|
|
||||||
abstract putSchedule(param): Observable<any>;
|
|
||||||
|
|
||||||
abstract getSchedule(): Observable<any>;
|
|
||||||
|
|
||||||
abstract getLog(id): Observable<any>;
|
|
||||||
|
|
||||||
abstract getStatus(id): Observable<any>;
|
|
||||||
|
|
||||||
abstract getJobs(): Observable<any>;
|
|
||||||
|
|
||||||
abstract getLogLink(id): string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class GcApiDefaultRepository extends GcApiRepository {
|
|
||||||
constructor(
|
|
||||||
private http: HttpClient
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public postSchedule(param): Observable<any> {
|
|
||||||
return this.http.post(`${CURRENT_BASE_HREF}/system/gc/schedule`, param)
|
|
||||||
.pipe(catchError(error => observableThrowError(error)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public putSchedule(param): Observable<any> {
|
|
||||||
return this.http.put(`${CURRENT_BASE_HREF}/system/gc/schedule`, param)
|
|
||||||
.pipe(catchError(error => observableThrowError(error)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSchedule(): Observable<any> {
|
|
||||||
return this.http.get(`${CURRENT_BASE_HREF}/system/gc/schedule`)
|
|
||||||
.pipe(catchError(error => observableThrowError(error)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public getLog(id): Observable<any> {
|
|
||||||
return this.http.get(`${CURRENT_BASE_HREF}/system/gc/${id}/log`)
|
|
||||||
.pipe(catchError(error => observableThrowError(error)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public getStatus(id): Observable<any> {
|
|
||||||
return this.http.get(`${CURRENT_BASE_HREF}/system/gc/${id}`)
|
|
||||||
.pipe(catchError(error => observableThrowError(error)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public getJobs(): Observable<any> {
|
|
||||||
return this.http.get(`${CURRENT_BASE_HREF}/system/gc`)
|
|
||||||
.pipe(catchError(error => observableThrowError(error)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public getLogLink(id) {
|
|
||||||
return `${CURRENT_BASE_HREF}/system/gc/${id}/log`;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
<div class="cron-selection">
|
<div class="cron-selection">
|
||||||
<cron-selection [labelCurrent]="getLabelCurrent" #CronScheduleComponent [labelEdit]='getLabelCurrent'
|
<cron-selection [labelCurrent]="getLabelCurrent" #CronScheduleComponent [labelEdit]='getLabelCurrent'
|
||||||
[originCron]='originCron' (inputvalue)="scheduleGc($event)"></cron-selection>
|
[originCron]='originCron' (inputvalue)="saveGcSchedule($event)"></cron-selection>
|
||||||
</div>
|
</div>
|
||||||
<div class="clr-row">
|
<div class="clr-row">
|
||||||
<div class="clr-col-2 flex-200"></div>
|
<div class="clr-col-2 flex-200"></div>
|
||||||
@ -22,11 +22,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="clr-row">
|
<div class="clr-row">
|
||||||
<div class="clr-col-2 flex-200">
|
<div class="clr-col-2 flex-200">
|
||||||
<button class="btn btn-primary gc-start-btn" (click)="gcNow()"
|
<button id="gc-now" class="btn btn-primary gc-start-btn" (click)="gcNow()"
|
||||||
[disabled]="disableGC">{{'GC.GC_NOW' | translate}}</button>
|
[disabled]="disableGC">{{'GC.GC_NOW' | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="clr-col">
|
<div class="clr-col">
|
||||||
<button class="btn btn-outline gc-start-btn" (click)="dryRun()"
|
<button id="gc-dry-run" class="btn btn-outline gc-start-btn" (click)="dryRun()"
|
||||||
[disabled]="dryRunOnGoing">{{'TAG_RETENTION.WHAT_IF_RUN' | translate}}</button>
|
[disabled]="dryRunOnGoing">{{'TAG_RETENTION.WHAT_IF_RUN' | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,35 +1,18 @@
|
|||||||
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { GcComponent } from './gc.component';
|
import { GcComponent } from './gc.component';
|
||||||
import { GcApiRepository, GcApiDefaultRepository} from './gc.api.repository';
|
|
||||||
import { GcRepoService } from './gc.service';
|
|
||||||
import { ErrorHandler } from '../../../../shared/units/error-handler';
|
import { ErrorHandler } from '../../../../shared/units/error-handler';
|
||||||
import { GcViewModelFactory } from './gc.viewmodel.factory';
|
|
||||||
import { CronScheduleComponent } from '../../../../shared/components/cron-schedule';
|
import { CronScheduleComponent } from '../../../../shared/components/cron-schedule';
|
||||||
import { CronTooltipComponent } from "../../../../shared/components/cron-schedule";
|
import { CronTooltipComponent } from "../../../../shared/components/cron-schedule";
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { GcJobData } from './gcLog';
|
|
||||||
import { CURRENT_BASE_HREF } from "../../../../shared/units/utils";
|
|
||||||
import { SharedTestingModule } from "../../../../shared/shared.module";
|
import { SharedTestingModule } from "../../../../shared/shared.module";
|
||||||
|
import { GcService } from "../../../../../../ng-swagger-gen/services/gc.service";
|
||||||
|
import { ScheduleType } from "../../../../shared/entities/shared.const";
|
||||||
|
|
||||||
describe('GcComponent', () => {
|
describe('GcComponent', () => {
|
||||||
let component: GcComponent;
|
let component: GcComponent;
|
||||||
let fixture: ComponentFixture<GcComponent>;
|
let fixture: ComponentFixture<GcComponent>;
|
||||||
let gcRepoService: GcRepoService;
|
let gcRepoService: GcService;
|
||||||
let mockSchedule = [];
|
let mockSchedule = [];
|
||||||
let mockJobs: GcJobData[] = [
|
|
||||||
{
|
|
||||||
id: 22222,
|
|
||||||
schedule: null,
|
|
||||||
job_status: 'string',
|
|
||||||
job_parameters: '{"dry_run":true}',
|
|
||||||
creation_time: new Date().toDateString(),
|
|
||||||
update_time: new Date().toDateString(),
|
|
||||||
job_name: 'string',
|
|
||||||
job_kind: 'string',
|
|
||||||
job_uuid: 'string',
|
|
||||||
delete: false
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const fakedErrorHandler = {
|
const fakedErrorHandler = {
|
||||||
error(error) {
|
error(error) {
|
||||||
return error;
|
return error;
|
||||||
@ -39,7 +22,6 @@ describe('GcComponent', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let spySchedule: jasmine.Spy;
|
let spySchedule: jasmine.Spy;
|
||||||
let spyJobs: jasmine.Spy;
|
|
||||||
let spyGcNow: jasmine.Spy;
|
let spyGcNow: jasmine.Spy;
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@ -48,10 +30,7 @@ describe('GcComponent', () => {
|
|||||||
],
|
],
|
||||||
declarations: [ GcComponent, CronScheduleComponent, CronTooltipComponent],
|
declarations: [ GcComponent, CronScheduleComponent, CronTooltipComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: GcApiRepository, useClass: GcApiDefaultRepository },
|
|
||||||
{ provide: ErrorHandler, useValue: fakedErrorHandler },
|
{ provide: ErrorHandler, useValue: fakedErrorHandler },
|
||||||
GcRepoService,
|
|
||||||
GcViewModelFactory
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
@ -61,10 +40,9 @@ describe('GcComponent', () => {
|
|||||||
fixture = TestBed.createComponent(GcComponent);
|
fixture = TestBed.createComponent(GcComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
||||||
gcRepoService = fixture.debugElement.injector.get(GcRepoService);
|
gcRepoService = fixture.debugElement.injector.get(GcService);
|
||||||
spySchedule = spyOn(gcRepoService, "getSchedule").and.returnValues(of(mockSchedule));
|
spySchedule = spyOn(gcRepoService, "getGCSchedule").and.returnValues(of(mockSchedule));
|
||||||
spyJobs = spyOn(gcRepoService, "getJobs").and.returnValues(of(mockJobs));
|
spyGcNow = spyOn(gcRepoService, "createGCSchedule").and.returnValues(of(true));
|
||||||
spyGcNow = spyOn(gcRepoService, "manualGc").and.returnValues(of(true));
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
@ -72,12 +50,25 @@ describe('GcComponent', () => {
|
|||||||
});
|
});
|
||||||
it('should get schedule and job', () => {
|
it('should get schedule and job', () => {
|
||||||
expect(spySchedule.calls.count()).toEqual(1);
|
expect(spySchedule.calls.count()).toEqual(1);
|
||||||
expect(spyJobs.calls.count()).toEqual(1);
|
|
||||||
});
|
});
|
||||||
it('should trigger gcNow', () => {
|
it('should trigger gcNow', () => {
|
||||||
const ele: HTMLButtonElement = fixture.nativeElement.querySelector('.gc-start-btn');
|
const ele: HTMLButtonElement = fixture.nativeElement.querySelector('#gc-now');
|
||||||
ele.click();
|
ele.click();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(spyGcNow.calls.count()).toEqual(1);
|
expect(spyGcNow.calls.count()).toEqual(1);
|
||||||
});
|
});
|
||||||
|
it('should trigger dry run', () => {
|
||||||
|
const ele: HTMLButtonElement = fixture.nativeElement.querySelector('#gc-dry-run');
|
||||||
|
ele.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(spyGcNow.calls.count()).toEqual(1);
|
||||||
|
});
|
||||||
|
it('getScheduleType function should work', () => {
|
||||||
|
expect(GcComponent.getScheduleType).toBeTruthy();
|
||||||
|
expect(GcComponent.getScheduleType(null)).toEqual(ScheduleType.NONE);
|
||||||
|
expect(GcComponent.getScheduleType('0 0 0 0 0 0')).toEqual(ScheduleType.CUSTOM);
|
||||||
|
expect(GcComponent.getScheduleType('0 0 * * * *')).toEqual(ScheduleType.HOURLY);
|
||||||
|
expect(GcComponent.getScheduleType('0 0 0 * * *')).toEqual(ScheduleType.DAILY);
|
||||||
|
expect(GcComponent.getScheduleType('0 0 0 * * 0')).toEqual(ScheduleType.WEEKLY);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,32 +1,26 @@
|
|||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
Input,
|
|
||||||
Output,
|
Output,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
OnInit
|
OnInit
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { TranslateService } from "@ngx-translate/core";
|
|
||||||
import { GcJobViewModel } from "./gcLog";
|
|
||||||
import { GcViewModelFactory } from "./gc.viewmodel.factory";
|
|
||||||
import { GcRepoService } from "./gc.service";
|
|
||||||
import {
|
|
||||||
SCHEDULE_TYPE_NONE,
|
|
||||||
ONE_MINITUE,
|
|
||||||
THREE_SECONDS, GCSchedule
|
|
||||||
} from "./gc.const";
|
|
||||||
import { ErrorHandler } from "../../../../shared/units/error-handler";
|
import { ErrorHandler } from "../../../../shared/units/error-handler";
|
||||||
import { CronScheduleComponent } from "../../../../shared/components/cron-schedule/cron-schedule.component";
|
import { CronScheduleComponent } from "../../../../shared/components/cron-schedule";
|
||||||
import { OriginCron } from '../../../../shared/services/interface';
|
import { OriginCron } from '../../../../shared/services';
|
||||||
import { finalize } from "rxjs/operators";
|
import { finalize } from "rxjs/operators";
|
||||||
|
import { GcService } from "../../../../../../ng-swagger-gen/services/gc.service";
|
||||||
|
import { GCHistory } from "../../../../../../ng-swagger-gen/models/gchistory";
|
||||||
|
import { ScheduleType } from "../../../../shared/entities/shared.const";
|
||||||
|
|
||||||
|
const ONE_MINUTE = 60000;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "gc-config",
|
selector: "gc-config",
|
||||||
templateUrl: "./gc.component.html",
|
templateUrl: "./gc.component.html",
|
||||||
styleUrls: ["./gc.component.scss"]
|
styleUrls: ["./gc.component.scss"]
|
||||||
})
|
})
|
||||||
export class GcComponent implements OnInit {
|
export class GcComponent implements OnInit {
|
||||||
jobs: Array<GcJobViewModel> = [];
|
|
||||||
schedule: GCSchedule = {};
|
|
||||||
originCron: OriginCron;
|
originCron: OriginCron;
|
||||||
disableGC: boolean = false;
|
disableGC: boolean = false;
|
||||||
getLabelCurrent = 'GC.CURRENT_SCHEDULE';
|
getLabelCurrent = 'GC.CURRENT_SCHEDULE';
|
||||||
@ -35,67 +29,66 @@ export class GcComponent implements OnInit {
|
|||||||
CronScheduleComponent: CronScheduleComponent;
|
CronScheduleComponent: CronScheduleComponent;
|
||||||
shouldDeleteUntagged: boolean;
|
shouldDeleteUntagged: boolean;
|
||||||
dryRunOnGoing: boolean = false;
|
dryRunOnGoing: boolean = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private gcRepoService: GcRepoService,
|
private gcService: GcService,
|
||||||
private gcViewModelFactory: GcViewModelFactory,
|
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
translate.setDefaultLang("en-us");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.getCurrentSchedule();
|
this.getCurrentSchedule();
|
||||||
this.getJobs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentSchedule() {
|
getCurrentSchedule() {
|
||||||
this.loadingGcStatus.emit(true);
|
this.loadingGcStatus.emit(true);
|
||||||
this.gcRepoService.getSchedule()
|
this.gcService.getGCSchedule()
|
||||||
.pipe(finalize(() => {
|
.pipe(finalize(() => {
|
||||||
this.loadingGcStatus.emit(false);
|
this.loadingGcStatus.emit(false);
|
||||||
}))
|
}))
|
||||||
.subscribe(schedule => {
|
.subscribe(schedule => {
|
||||||
this.initSchedule(schedule);
|
this.initSchedule(schedule);
|
||||||
}, error => {
|
}, error => {
|
||||||
this.errorHandler.error(error);
|
this.errorHandler.error(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public initSchedule(schedule: GCSchedule) {
|
private initSchedule(gcHistory: GCHistory) {
|
||||||
if (schedule && schedule.schedule !== null) {
|
if (gcHistory && gcHistory.schedule) {
|
||||||
this.schedule = schedule;
|
this.originCron = {
|
||||||
this.originCron = this.schedule.schedule;
|
type: gcHistory.schedule.type,
|
||||||
|
cron: gcHistory.schedule.cron
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
this.originCron = {
|
this.originCron = {
|
||||||
type: SCHEDULE_TYPE_NONE,
|
type: ScheduleType.NONE,
|
||||||
cron: ''
|
cron: ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (schedule && schedule.job_parameters) {
|
if (gcHistory && gcHistory.job_parameters) {
|
||||||
this.shouldDeleteUntagged = JSON.parse(schedule.job_parameters).delete_untagged;
|
this.shouldDeleteUntagged = JSON.parse(gcHistory.job_parameters).delete_untagged;
|
||||||
} else {
|
} else {
|
||||||
this.shouldDeleteUntagged = false;
|
this.shouldDeleteUntagged = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getJobs() {
|
|
||||||
this.gcRepoService.getJobs().subscribe(jobs => {
|
|
||||||
this.jobs = this.gcViewModelFactory.createJobViewModel(jobs);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
gcNow(): void {
|
gcNow(): void {
|
||||||
this.disableGC = true;
|
this.disableGC = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.enableGc();
|
this.enableGc();
|
||||||
}, ONE_MINITUE);
|
}, ONE_MINUTE);
|
||||||
|
|
||||||
this.gcRepoService.manualGc(this.shouldDeleteUntagged, false).subscribe(
|
this.gcService.createGCSchedule({
|
||||||
|
parameters: {
|
||||||
|
delete_untagged: this.shouldDeleteUntagged,
|
||||||
|
dry_run: false
|
||||||
|
},
|
||||||
|
schedule: {
|
||||||
|
type: ScheduleType.MANUAL
|
||||||
|
}
|
||||||
|
}).subscribe(
|
||||||
response => {
|
response => {
|
||||||
this.translate.get("GC.MSG_SUCCESS").subscribe((res: string) => {
|
this.errorHandler.info("GC.MSG_SUCCESS");
|
||||||
this.errorHandler.info(res);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.errorHandler.error(error);
|
this.errorHandler.error(error);
|
||||||
@ -105,62 +98,66 @@ export class GcComponent implements OnInit {
|
|||||||
|
|
||||||
dryRun() {
|
dryRun() {
|
||||||
this.dryRunOnGoing = true;
|
this.dryRunOnGoing = true;
|
||||||
this.gcRepoService.manualGc(this.shouldDeleteUntagged, true)
|
this.gcService.createGCSchedule({
|
||||||
|
parameters: {
|
||||||
|
delete_untagged: this.shouldDeleteUntagged,
|
||||||
|
dry_run: true
|
||||||
|
},
|
||||||
|
schedule: {
|
||||||
|
type: ScheduleType.MANUAL
|
||||||
|
}
|
||||||
|
})
|
||||||
.pipe(finalize(() => this.dryRunOnGoing = false))
|
.pipe(finalize(() => this.dryRunOnGoing = false))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
response => {
|
response => {
|
||||||
this.translate.get("GC.DRY_RUN_SUCCESS").subscribe((res: string) => {
|
this.errorHandler.info("GC.DRY_RUN_SUCCESS");
|
||||||
this.errorHandler.info(res);
|
},
|
||||||
});
|
error => {
|
||||||
},
|
this.errorHandler.error(error);
|
||||||
error => {
|
}
|
||||||
this.errorHandler.error(error);
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enableGc() {
|
private enableGc() {
|
||||||
this.disableGC = false;
|
this.disableGC = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private resetSchedule(cron) {
|
saveGcSchedule(cron: string) {
|
||||||
this.schedule = {
|
if (this.originCron && this.originCron.type !== ScheduleType.NONE) {// no schedule, then create
|
||||||
schedule: {
|
this.gcService.createGCSchedule({
|
||||||
type: this.CronScheduleComponent.scheduleType,
|
parameters: {
|
||||||
cron: cron
|
delete_untagged: this.shouldDeleteUntagged,
|
||||||
}
|
dry_run: false
|
||||||
};
|
},
|
||||||
if (!cron) {
|
schedule: {
|
||||||
this.shouldDeleteUntagged = false;
|
type: GcComponent.getScheduleType(cron),
|
||||||
}
|
cron: cron
|
||||||
this.getJobs();
|
}
|
||||||
}
|
}).subscribe(
|
||||||
|
|
||||||
scheduleGc(cron: string) {
|
|
||||||
let schedule = this.schedule;
|
|
||||||
if (schedule && schedule.schedule && schedule.schedule.type !== SCHEDULE_TYPE_NONE) {
|
|
||||||
this.gcRepoService.putScheduleGc(this.shouldDeleteUntagged, this.CronScheduleComponent.scheduleType, cron).subscribe(
|
|
||||||
response => {
|
response => {
|
||||||
this.translate
|
this.errorHandler.info("GC.MSG_SCHEDULE_RESET");
|
||||||
.get("GC.MSG_SCHEDULE_RESET")
|
this.CronScheduleComponent.resetSchedule();
|
||||||
.subscribe((res) => {
|
this.getCurrentSchedule(); // refresh schedule
|
||||||
this.errorHandler.info(res);
|
|
||||||
this.CronScheduleComponent.resetSchedule();
|
|
||||||
});
|
|
||||||
this.resetSchedule(cron);
|
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.errorHandler.error(error);
|
this.errorHandler.error(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.gcRepoService.postScheduleGc(this.shouldDeleteUntagged, this.CronScheduleComponent.scheduleType, cron).subscribe(
|
this.gcService.updateGCSchedule({
|
||||||
|
parameters: {
|
||||||
|
delete_untagged: this.shouldDeleteUntagged,
|
||||||
|
dry_run: false
|
||||||
|
},
|
||||||
|
schedule: {
|
||||||
|
type: GcComponent.getScheduleType(cron),
|
||||||
|
cron: cron
|
||||||
|
}
|
||||||
|
}).subscribe(
|
||||||
response => {
|
response => {
|
||||||
this.translate.get("GC.MSG_SCHEDULE_SET").subscribe((res) => {
|
this.errorHandler.info("GC.MSG_SCHEDULE_RESET");
|
||||||
this.errorHandler.info(res);
|
this.CronScheduleComponent.resetSchedule();
|
||||||
this.CronScheduleComponent.resetSchedule();
|
this.getCurrentSchedule(); // refresh schedule
|
||||||
});
|
|
||||||
this.resetSchedule(cron);
|
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.errorHandler.error(error);
|
this.errorHandler.error(error);
|
||||||
@ -168,4 +165,20 @@ export class GcComponent implements OnInit {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getScheduleType(cron: string): 'Hourly' | 'Daily' | 'Weekly' | 'Custom' | 'Manual' | 'None' {
|
||||||
|
if (cron) {
|
||||||
|
if (cron === '0 0 * * * *') {
|
||||||
|
return ScheduleType.HOURLY;
|
||||||
|
}
|
||||||
|
if (cron === '0 0 0 * * *') {
|
||||||
|
return ScheduleType.DAILY;
|
||||||
|
}
|
||||||
|
if (cron === '0 0 0 * * 0') {
|
||||||
|
return ScheduleType.WEEKLY;
|
||||||
|
}
|
||||||
|
return ScheduleType.CUSTOM;
|
||||||
|
}
|
||||||
|
return ScheduleType.NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import { OriginCron } from "../../../../shared/services";
|
|
||||||
|
|
||||||
|
|
||||||
export const SCHEDULE_TYPE_NONE = "None";
|
|
||||||
|
|
||||||
export const ONE_MINITUE = 60000;
|
|
||||||
export const THREE_SECONDS = 3000;
|
|
||||||
|
|
||||||
export interface GCSchedule {
|
|
||||||
schedule?: OriginCron;
|
|
||||||
parameters?: {[key: string]: any};
|
|
||||||
id?: number;
|
|
||||||
job_name?: string;
|
|
||||||
job_kind?: string;
|
|
||||||
job_parameters?: string;
|
|
||||||
job_status?: string;
|
|
||||||
deleted?: boolean;
|
|
||||||
creation_time?: Date;
|
|
||||||
update_time?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { Observable, Subscription, Subject, of } from 'rxjs';
|
|
||||||
import { catchError, map } from 'rxjs/operators';
|
|
||||||
import { GcApiRepository } from './gc.api.repository';
|
|
||||||
import { ErrorHandler } from '../../../../shared/units/error-handler';
|
|
||||||
import { GcJobData } from './gcLog';
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class GcRepoService {
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private gcApiRepository: GcApiRepository,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public manualGc(shouldDeleteUntagged: boolean, isDryRun: boolean): Observable<any> {
|
|
||||||
const param = {
|
|
||||||
"schedule": {
|
|
||||||
"type": "Manual"
|
|
||||||
},
|
|
||||||
parameters: {
|
|
||||||
delete_untagged: shouldDeleteUntagged,
|
|
||||||
dry_run: isDryRun
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return this.gcApiRepository.postSchedule(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getJobs(): Observable <GcJobData []> {
|
|
||||||
return this.gcApiRepository.getJobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getLog(id): Observable <any> {
|
|
||||||
return this.gcApiRepository.getLog(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSchedule(): Observable <any> {
|
|
||||||
return this.gcApiRepository.getSchedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
public postScheduleGc(shouldDeleteUntagged: boolean, type, cron): Observable <any> {
|
|
||||||
let param = {
|
|
||||||
"schedule": {
|
|
||||||
"type": type,
|
|
||||||
"cron": cron,
|
|
||||||
},
|
|
||||||
parameters: {
|
|
||||||
delete_untagged: shouldDeleteUntagged
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.gcApiRepository.postSchedule(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
public putScheduleGc(shouldDeleteUntagged, type, cron): Observable <any> {
|
|
||||||
let param = {
|
|
||||||
"schedule": {
|
|
||||||
"type": type,
|
|
||||||
"cron": cron,
|
|
||||||
},
|
|
||||||
parameters: {
|
|
||||||
delete_untagged: shouldDeleteUntagged
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.gcApiRepository.putSchedule(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getLogLink(id): string {
|
|
||||||
return this.gcApiRepository.getLogLink(id);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { GcJobData, GcJobViewModel } from './gcLog';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class GcViewModelFactory {
|
|
||||||
public createJobViewModel(jobs: GcJobData[]): GcJobViewModel[] {
|
|
||||||
let gcViewModels: GcJobViewModel[] = [];
|
|
||||||
for (let job of jobs) {
|
|
||||||
|
|
||||||
let createTime = new Date(job.creation_time);
|
|
||||||
let updateTime = new Date(job.update_time);
|
|
||||||
gcViewModels.push({
|
|
||||||
id: job.id,
|
|
||||||
type: job.schedule ? job.schedule.type : null,
|
|
||||||
status: job.job_status,
|
|
||||||
parameters: job.job_parameters,
|
|
||||||
createTime: createTime,
|
|
||||||
updateTime: updateTime,
|
|
||||||
details: null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return gcViewModels;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
export class GcJobData {
|
|
||||||
id: number;
|
|
||||||
job_name: string;
|
|
||||||
job_kind: string;
|
|
||||||
schedule: Schedule;
|
|
||||||
job_status: string;
|
|
||||||
job_parameters: string;
|
|
||||||
job_uuid: string;
|
|
||||||
creation_time: string;
|
|
||||||
update_time: string;
|
|
||||||
delete: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Schedule {
|
|
||||||
type: string;
|
|
||||||
cron: string;
|
|
||||||
}
|
|
||||||
export class GcJobViewModel {
|
|
||||||
id: number;
|
|
||||||
type: string;
|
|
||||||
status: string;
|
|
||||||
parameters: string;
|
|
||||||
createTime: Date;
|
|
||||||
updateTime: Date;
|
|
||||||
details: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -242,3 +242,12 @@ export enum ResourceType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const CARD_VIEW_LOCALSTORAGE_KEY = 'card-view';
|
export const CARD_VIEW_LOCALSTORAGE_KEY = 'card-view';
|
||||||
|
|
||||||
|
export enum ScheduleType {
|
||||||
|
NONE = "None",
|
||||||
|
DAILY = "Daily",
|
||||||
|
WEEKLY = "Weekly",
|
||||||
|
HOURLY = "Hourly",
|
||||||
|
CUSTOM = "Custom",
|
||||||
|
MANUAL = 'Manual'
|
||||||
|
}
|
||||||
|
@ -47,4 +47,4 @@ export abstract class ErrorHandler {
|
|||||||
abstract log(log: any): void;
|
abstract log(log: any): void;
|
||||||
|
|
||||||
abstract handleErrorPopupUnauthorized(error: any): void;
|
abstract handleErrorPopupUnauthorized(error: any): void;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user