Update replication data

Signed-off-by: FangyuanCheng <fangyuanc@vmware.com>
This commit is contained in:
FangyuanCheng 2019-03-31 18:00:44 +08:00
parent 82e02fc734
commit cb438d0029
15 changed files with 157 additions and 206 deletions

View File

@ -17,7 +17,7 @@
<div class="form-select">
<div class="select providerSelect pull-left">
<select name="adapter" id="adapter" [(ngModel)]="target.type" [disabled]="testOngoing || controlEnabled">
<option *ngFor="let adapter of adapterList" [ngValue]="adapter" value="{{adapter}}">{{adapter}}</option>
<option *ngFor="let adapter of adapterList" value="{{adapter}}">{{adapter}}</option>
</select>
</div>
</div>

View File

@ -12,7 +12,7 @@ import { FilterComponent } from "../filter/filter.component";
import { CreateEditEndpointComponent } from "../create-edit-endpoint/create-edit-endpoint.component";
import { InlineAlertComponent } from "../inline-alert/inline-alert.component";
import { ErrorHandler } from "../error-handler/error-handler";
import { Endpoint, Adapter } from "../service/interface";
import { Endpoint } from "../service/interface";
import {
EndpointService,
EndpointDefaultService
@ -34,17 +34,7 @@ describe("CreateEditEndpointComponent (inline template)", () => {
url: "https://10.117.4.151"
};
let mockAdapters: Adapter[] = [{
type: "Harbor",
description: "test",
supported_resource_filters: [
{
"type": "Name",
"style": "input"
}
],
supported_triggers: []
}];
let mockAdapters = ['harbor', 'docker hub'];
let comp: CreateEditEndpointComponent;
let fixture: ComponentFixture<CreateEditEndpointComponent>;

View File

@ -28,7 +28,7 @@ import { TranslateService } from "@ngx-translate/core";
import { EndpointService } from "../service/endpoint.service";
import { ErrorHandler } from "../error-handler/index";
import { InlineAlertComponent } from "../inline-alert/inline-alert.component";
import { Endpoint, Adapter } from "../service/interface";
import { Endpoint } from "../service/interface";
import { clone, compareValue, isEmptyObject } from "../utils";
@ -48,7 +48,7 @@ export class CreateEditEndpointComponent
staticBackdrop: boolean = true;
closable: boolean = false;
editable: boolean;
adapterList: Adapter[] = [];
adapterList: string[];
target: Endpoint = this.initEndpoint();
selectedType: string;
initVal: Endpoint;
@ -117,7 +117,7 @@ export class CreateEditEndpointComponent
description: "",
insecure: false,
name: "",
type: "Harbor",
type: "harbor",
url: "",
};
}

View File

@ -17,8 +17,7 @@ import {
ReplicationRule,
ReplicationJob,
Endpoint,
ReplicationJobItem,
Adapter
ReplicationJobItem
} from "../service/interface";
import { ErrorHandler } from "../error-handler/error-handler";
@ -42,19 +41,6 @@ import { RouterTestingModule } from '@angular/router/testing';
import { of } from "rxjs";
describe("CreateEditRuleComponent (inline template)", () => {
let mockEndpoint: Endpoint = {
id: 1,
credential: {
access_key: "admin",
access_secret: "",
type: "basic"
},
description: "test",
insecure: false,
name: "target_01",
type: "Harbor",
url: "https://10.117.4.151"
};
let mockRules: ReplicationRule[] = [
{
id: 1,
@ -74,26 +60,35 @@ describe("CreateEditRuleComponent (inline template)", () => {
{
id: 1,
status: "stopped",
repository: "library/busybox",
policy_id: 1,
operation: "transfer",
tags: null
trigger: "Manual",
total: 0,
failed: 0,
succeed: 0,
in_progress: 0,
stopped: 0
},
{
id: 2,
status: "stopped",
repository: "library/busybox",
policy_id: 1,
operation: "transfer",
tags: null
trigger: "Manual",
total: 1,
failed: 0,
succeed: 1,
in_progress: 0,
stopped: 0
},
{
id: 3,
status: "stopped",
repository: "library/busybox",
policy_id: 2,
operation: "transfer",
tags: null
trigger: "Manual",
total: 1,
failed: 1,
succeed: 0,
in_progress: 0,
stopped: 0
}
];
@ -171,7 +166,7 @@ describe("CreateEditRuleComponent (inline template)", () => {
deletion: false
};
let mockAdapter: Adapter = {
let mockAdapter = {
"type": "harbor",
"description": "",
"supported_resource_filters": [
@ -218,7 +213,6 @@ describe("CreateEditRuleComponent (inline template)", () => {
let spyJobs: jasmine.Spy;
let spyAdapter: jasmine.Spy;
let spyEndpoint: jasmine.Spy;
let spyEndpoints: jasmine.Spy;
let config: IServiceConfig = {
@ -277,14 +271,10 @@ describe("CreateEditRuleComponent (inline template)", () => {
spyAdapter = spyOn(replicationService, "getReplicationAdapter").and.returnValues(
of(mockAdapter));
spyEndpoints = spyOn(endpointService, "getEndpoints").and.returnValues(
spyEndpoint = spyOn(endpointService, "getEndpoints").and.returnValues(
of(mockEndpoints)
);
spyEndpoint = spyOn(endpointService, "getEndpoint").and.returnValue(
of(mockEndpoint)
);
fixture.detectChanges();
});

View File

@ -21,7 +21,7 @@ import {
EventEmitter,
Output
} from "@angular/core";
import { Filter, ReplicationRule, Endpoint, Adapter } from "../service/interface";
import { Filter, ReplicationRule, Endpoint } from "../service/interface";
import { Subject, Subscription } from "rxjs";
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
import { FormArray, FormBuilder, FormGroup, Validators, FormControl } from "@angular/forms";

View File

@ -10,7 +10,7 @@ import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation
import { CreateEditEndpointComponent } from "../create-edit-endpoint/create-edit-endpoint.component";
import { InlineAlertComponent } from "../inline-alert/inline-alert.component";
import { ErrorHandler } from "../error-handler/error-handler";
import { Endpoint, Adapter } from "../service/interface";
import { Endpoint } from "../service/interface";
import {
EndpointService,
EndpointDefaultService
@ -93,17 +93,7 @@ describe("EndpointComponent (inline template)", () => {
}
];
let mockAdapters: Adapter[] = [{
type: "Harbor",
description: "test",
supported_resource_filters: [
{
"type": "Name",
"style": "input"
}
],
supported_triggers: []
}];
let mockAdapters = ['harbor', 'docker hub'];
let comp: EndpointComponent;
let fixture: ComponentFixture<EndpointComponent>;

View File

@ -16,7 +16,7 @@
<clr-dg-row *clrDgItems="let p of changedRules; let i=index" [clrDgItem]="p" [style.backgroundColor]="(projectScope && withReplicationJob && selectedId === p.id) ? '#eee' : ''">
<clr-dg-cell>{{p.name}}</clr-dg-cell>
<clr-dg-cell class="min-width">
{{p.src_registry_id? registryName[i]:'current'}} : {{p.src_namespaces?.length>0 ? p.src_namespaces[0]: ''}}
{{p.src_registry ? p.src_registry.name : ''}} : {{p.src_namespaces?.length>0 ? p.src_namespaces[0]: ''}}
<clr-tooltip>
<clr-icon *ngIf="p.src_namespaces && p.src_namespaces.length > 1" clrTooltipTrigger shape="ellipsis-horizontal" size="18"></clr-icon>
<clr-tooltip-content clrPosition="top-right" clrSize="md" *clrIfOpen>
@ -25,10 +25,10 @@
</clr-tooltip>
</clr-dg-cell>
<clr-dg-cell>
{{p.src_registry_id>0? 'pull-based' : 'push-based'}}
{{p.src_registry && p.src_registry.id > 0 ? 'pull-based' : 'push-based'}}
</clr-dg-cell>
<clr-dg-cell class="min-width">
{{p.dest_registry_id? registryName[i]: 'current'}} : {{p.dest_namespace? p.dest_namespace: ''}}
{{p.dest_registry ? p.dest_registry.name : ''}} : {{p.dest_namespace? p.dest_namespace: ''}}
</clr-dg-cell>
<clr-dg-cell>{{p.trigger ? p.trigger.type : ''}}</clr-dg-cell>
<clr-dg-cell>

View File

@ -15,23 +15,8 @@ import { SERVICE_CONFIG, IServiceConfig } from '../service.config';
import { ReplicationService, ReplicationDefaultService } from '../service/replication.service';
import { OperationService } from "../operation/operation.service";
import { of } from 'rxjs';
import { EndpointService, EndpointDefaultService } from "../service/endpoint.service";
import { Endpoint } from "../service/interface";
describe('ListReplicationRuleComponent (inline template)', () => {
let mockEndpoint: Endpoint = {
id: 1,
credential: {
access_key: "admin",
access_secret: "",
type: "basic"
},
description: "test",
insecure: false,
name: "target_01",
type: "Harbor",
url: "https://10.117.4.151"
};
let mockRules: ReplicationRule[] = [
{
@ -64,16 +49,10 @@ describe('ListReplicationRuleComponent (inline template)', () => {
let replicationService: ReplicationService;
let endpointService: EndpointService;
let spyRules: jasmine.Spy;
let spyEndpoint: jasmine.Spy;
let config: IServiceConfig = {
replicationRuleEndpoint: '/api/policies/replication/testing',
systemInfoEndpoint: "/api/endpoints/testing"
replicationRuleEndpoint: '/api/policies/replication/testing'
};
beforeEach(async(() => {
@ -90,8 +69,7 @@ describe('ListReplicationRuleComponent (inline template)', () => {
ErrorHandler,
{ provide: SERVICE_CONFIG, useValue: config },
{ provide: ReplicationService, useClass: ReplicationDefaultService },
{ provide: OperationService },
{ provide: EndpointService, useClass: EndpointDefaultService }
{ provide: OperationService }
]
});
}));
@ -102,10 +80,6 @@ describe('ListReplicationRuleComponent (inline template)', () => {
replicationService = fixture.debugElement.injector.get(ReplicationService);
spyRules = spyOn(replicationService, 'getReplicationRules').and.returnValues(of(mockRules));
endpointService = fixture.debugElement.injector.get(EndpointService);
spyEndpoint = spyOn(endpointService, "getEndpoint").and.returnValue(
of(mockEndpoint)
);
fixture.detectChanges();
});

View File

@ -29,7 +29,6 @@ import { TranslateService } from "@ngx-translate/core";
import { map, catchError } from "rxjs/operators";
import { Observable, forkJoin, of, throwError as observableThrowError } from "rxjs";
import { ReplicationService } from "../service/replication.service";
import { EndpointService } from "../service/endpoint.service";
import {
ReplicationJob,
ReplicationJobItem,
@ -82,9 +81,6 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
changedRules: ReplicationRule[];
ruleName: string;
canDeleteRule: boolean;
registryName: [] = [];
desRegistry: [] = [];
currentRegistry: string;
selectedRow: ReplicationRule;
@ -98,7 +94,6 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
enabledComparator: Comparator<ReplicationRule> = new CustomComparator<ReplicationRule>("enabled", "number");
constructor(private replicationService: ReplicationService,
private endpointService: EndpointService,
private translateService: TranslateService,
private errorHandler: ErrorHandler,
private operationService: OperationService,
@ -119,9 +114,6 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
if (!this.projectScope) {
this.retrieveRules();
}
this.translateService.get("REPLICATION.CURRENT").subscribe((res: string) => {
this.currentRegistry = res;
});
}
ngOnChanges(changes: SimpleChanges): void {
let proIdChange: SimpleChange = changes["projectId"];
@ -147,35 +139,12 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
this.hideJobs.emit();
this.changedRules = this.rules;
this.loading = false;
// get registry name
let targetLists: ReplicationRule[] = rules;
if (targetLists && targetLists.length) {
let registryList: any[] = [];
targetLists.forEach(target => {
let tartId: number;
if (target.src_registry_id > 0) {
tartId = target.src_registry_id;
} else {
tartId = target.dest_registry_id;
}
registryList.push(this.getRegistry(tartId));
});
forkJoin(...registryList).subscribe((item) => {
this.selectedRow = null;
this.registryName = item.map(target => target.name);
});
}
}, error => {
this.errorHandler.error(error);
this.loading = false;
});
}
getRegistry(endpointId) {
return this.endpointService.getEndpoint(endpointId);
}
replicateRule(rule: ReplicationRule): void {
this.replicateManual.emit(rule);
}

View File

@ -14,15 +14,15 @@
<h2 class="custom-h2 h2-style">{{executionId}}</h2>
</div>
<div>
<div class="status-progress" *ngIf="executions === 'InProgress'">
<div class="status-progress" *ngIf="executions && executions['status'] === 'InProgress'">
<span class="spinner spinner-inline"></span>
<span>{{'REPLICATION.IN_PROGRESS'| translate}}</span>
</div>
<div class="status-success" *ngIf="executions === 'success'">
<div class="status-success" *ngIf="executions && executions['status'] === 'Succeed'">
<clr-icon size="18" shape="success-standard" class="color-green"></clr-icon>
<span>{{'REPLICATION.SUCCESS'| translate}}</span>
</div>
<div class="status-failed" *ngIf="executions === 'failed'">
<div class="status-failed" *ngIf="executions && executions['status'] === 'Failed'">
<clr-icon size="18" shape="error-standard" class="color-red"></clr-icon>
<span>{{'REPLICATION.FAILTURE'| translate}}</span>
</div>
@ -37,17 +37,13 @@
</div>
<div class="execution-block">
<div class="executions-detail">
<div class="policy">
<label>{{'REPLICATION.POLICY' | translate}} :</label>
<span>{{'My 1st policy'}}</span>
<div>
<label>{{'REPLICATION.TRIGGER_MODE' | translate}} :</label>
<span>{{trigger| translate}}</span>
</div>
<div class="trigger">
<label for="">{{'REPLICATION.TRIGGER_MODE' | translate}} :</label>
<span>{{'Schedule'}}</span>
</div>
<div class="start-time">
<label for="">{{'REPLICATION.CREATION_TIME' | translate}} :</label>
<span>{{'3/14/19, 2:26 PM'}}</span>
<div>
<label>{{'REPLICATION.CREATION_TIME' | translate}} :</label>
<span>{{startTime | date: 'short'}}</span>
</div>
</div>
<div class="flex-block">

View File

@ -20,7 +20,7 @@ export class ReplicationTasksComponent implements OnInit {
tasks: ReplicationTasks[] = [];
tasksCopy: ReplicationTasks[] = [];
stopOnGoing: boolean;
executions: string = 'InProgress';
executions: ReplicationJobItem[];
@Input() executionId: string;
startTimeComparator: Comparator<ReplicationJob> = new CustomComparator<
ReplicationJob
@ -38,23 +38,33 @@ export class ReplicationTasksComponent implements OnInit {
ngOnInit(): void {
this.clrLoadTasks();
// this.executions.status = 'success';
this.searchTask = '';
this.getExecutionDetail();
}
// getExecutions(): void {
// if (this.executionId) {
// toPromise<ReplicationJob>(
// this.replicationService.getExecutions(this.executionId)
// )
// .then(executions => {
// console.log(executions);
// })
// .catch(error => {
// this.errorHandler.error(error);
// });
// }
// }
getExecutionDetail(): void {
if (this.executionId) {
this.replicationService.getExecutionById(this.executionId)
.subscribe(res => {
this.executions = res.data;
},
error => {
this.errorHandler.error(error);
});
}
}
public get trigger(): string {
return this.executions && this.executions['trigger']
? this.executions['trigger']
: "";
}
public get startTime(): Date {
return this.executions && this.executions['start_time']
? this.executions['start_time']
: null;
}
stopJob() {
this.stopOnGoing = true;

View File

@ -27,20 +27,6 @@ import { of } from 'rxjs';
describe('Replication Component (inline template)', () => {
let mockEndpoint: Endpoint = {
id: 1,
credential: {
access_key: "admin",
access_secret: "",
type: "basic"
},
description: "test",
insecure: false,
name: "target_01",
type: "Harbor",
url: "https://10.117.4.151"
};
let mockRules: ReplicationRule[] = [
{
@ -69,31 +55,37 @@ describe('Replication Component (inline template)', () => {
let mockJobs: ReplicationJobItem[] = [
{
"id": 1,
"status": "error",
"repository": "library/nginx",
"policy_id": 1,
"operation": "transfer",
"update_time": new Date("2017-05-23 12:20:33"),
"tags": null
id: 1,
status: "stopped",
policy_id: 1,
trigger: "Manual",
total: 0,
failed: 0,
succeed: 0,
in_progress: 0,
stopped: 0
},
{
"id": 2,
"status": "finished",
"repository": "library/mysql",
"policy_id": 1,
"operation": "transfer",
"update_time": new Date("2017-05-27 12:20:33"),
"tags": null
id: 2,
status: "stopped",
policy_id: 1,
trigger: "Manual",
total: 1,
failed: 0,
succeed: 1,
in_progress: 0,
stopped: 0
},
{
"id": 3,
"status": "stopped",
"repository": "library/busybox",
"policy_id": 2,
"operation": "transfer",
"update_time": new Date("2017-04-23 12:20:33"),
"tags": null
id: 3,
status: "stopped",
policy_id: 2,
trigger: "Manual",
total: 1,
failed: 1,
succeed: 0,
in_progress: 0,
stopped: 0
}
];
@ -141,7 +133,6 @@ describe('Replication Component (inline template)', () => {
let spyRules: jasmine.Spy;
let spyJobs: jasmine.Spy;
let spyEndpoint: jasmine.Spy;
let spyEndpoints: jasmine.Spy;
let deGrids: DebugElement[];
@ -152,8 +143,7 @@ describe('Replication Component (inline template)', () => {
let elJob: HTMLElement;
let config: IServiceConfig = {
replicationRuleEndpoint: '/api/policies/replication/testing',
systemInfoEndpoint: "/api/endpoints/testing"
replicationRuleEndpoint: '/api/policies/replication/testing'
};
beforeEach(async(() => {
@ -203,7 +193,6 @@ describe('Replication Component (inline template)', () => {
spyEndpoints = spyOn(endpointService, 'getEndpoints').and.returnValues(of(mockEndpoints));
spyEndpoint = spyOn(endpointService, "getEndpoint").and.returnValue(of(mockEndpoint));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();

View File

@ -9,7 +9,7 @@ import {
HTTP_GET_OPTIONS
} from "../utils";
import { RequestQueryParams } from "./RequestQueryParams";
import { Endpoint, ReplicationRule, Adapter } from "./interface";
import { Endpoint, ReplicationRule } from "./interface";
import { catchError, map } from "rxjs/operators";
@ -181,7 +181,7 @@ export class EndpointDefaultService extends EndpointService {
public getAdapters(): Observable<any> {
return this.http
.get(`/api/replication/adapters`)
.pipe(map(response => response.json() as Adapter)
.pipe(map(response => response.json())
, catchError(error => observableThrowError(error)));
}

View File

@ -93,13 +93,6 @@ export interface Filter {
values ?: string[];
}
export interface Adapter extends Base {
type: string;
description: string;
supported_triggers: string [];
supported_resource_filters: Filter [];
}
/**
* Interface for replication rule.
*
@ -163,10 +156,13 @@ export interface ReplicationJobItem extends Base {
[key: string]: any | any[];
id: number;
status: string;
repository: string;
policy_id: number;
operation: string;
tags: string;
trigger: string;
total: number;
failed: number;
succeed: number;
in_progress: number;
stopped: number;
}
/**

View File

@ -10,8 +10,7 @@ import {
ReplicationJob,
ReplicationRule,
ReplicationJobItem,
ReplicationTasks,
Adapter
ReplicationTasks
} from "./interface";
import { RequestQueryParams } from "./RequestQueryParams";
import { map, catchError } from "rxjs/operators";
@ -142,7 +141,7 @@ export abstract class ReplicationService {
): Observable<any>;
abstract getReplicationAdapter(type: string): Observable<Adapter>;
abstract getReplicationAdapter(type: string): Observable<any>;
/**
* Get the jobs for the specified replication rule.
@ -165,6 +164,19 @@ export abstract class ReplicationService {
queryParams?: RequestQueryParams
): Observable<ReplicationJob>;
/**
* Get the specified execution.
*
* @abstract
* ** deprecated param {(number | string)} endpointId
* returns {(Observable<ReplicationJob> | ReplicationJob)}
*
* @memberOf ReplicationService
*/
abstract getExecutionById(
executionId: number | string
): Observable<ReplicationJob>;
/**
* Get the log of the specified job.
*
@ -222,11 +234,11 @@ export class ReplicationDefaultService extends ReplicationService {
);
}
public getReplicationAdapter(type): Observable<Adapter> {
public getReplicationAdapter(type): Observable<any> {
let requestUrl: string = `${this._replicateUrl}/adapters/${type}`;
return this.http
.get(requestUrl)
.pipe(map(response => response.json() as Adapter)
.pipe(map(response => response.json())
, catchError(error => observableThrowError(error)));
}
@ -415,6 +427,41 @@ export class ReplicationDefaultService extends ReplicationService {
, catchError(error => observableThrowError(error)));
}
public getExecutionById(
executionId: number | string
): Observable<ReplicationJob> {
if (!executionId || executionId <= 0) {
return observableThrowError("Bad request argument.");
}
let requestUrl: string = `${this._replicateUrl}/executions/${executionId}`;
return this.http
.get(requestUrl, HTTP_GET_OPTIONS)
.pipe(map(response => {
let result: ReplicationJob = {
metadata: {
xTotalCount: 0
},
data: []
};
if (response && response.headers) {
let xHeader: string = response.headers.get("X-Total-Count");
if (xHeader) {
result.metadata.xTotalCount = parseInt(xHeader, 0);
}
}
result.data = response.json() as ReplicationJobItem[];
if (result.metadata.xTotalCount === 0) {
if (result.data && result.data.length > 0) {
result.metadata.xTotalCount = result.data.length;
}
}
return result;
})
, catchError(error => observableThrowError(error)));
}
public getJobLog(
jobId: number | string
): Observable<string> {