diff --git a/src/portal/lib/src/create-edit-endpoint/create-edit-endpoint.component.spec.ts b/src/portal/lib/src/create-edit-endpoint/create-edit-endpoint.component.spec.ts index 7e280d102..50bdd8b54 100644 --- a/src/portal/lib/src/create-edit-endpoint/create-edit-endpoint.component.spec.ts +++ b/src/portal/lib/src/create-edit-endpoint/create-edit-endpoint.component.spec.ts @@ -34,13 +34,16 @@ describe("CreateEditEndpointComponent (inline template)", () => { url: "https://10.117.4.151" }; - let mockAdapter: [Adapter] = [{ + let mockAdapters: Adapter[] = [{ type: "Harbor", description: "test", - supported_resource_types: [ - "repository" + supported_resource_filters: [ + { + "type": "Name", + "style": "input" + } ], - supported_resource_filters: null + supported_triggers: [] }]; let comp: CreateEditEndpointComponent; @@ -77,7 +80,7 @@ describe("CreateEditEndpointComponent (inline template)", () => { endpointService = fixture.debugElement.injector.get(EndpointService); spyAdapter = spyOn(endpointService, "getAdapters").and.returnValue( - of(mockAdapter) + of(mockAdapters) ); spy = spyOn(endpointService, "getEndpoint").and.returnValue( diff --git a/src/portal/lib/src/create-edit-rule/create-edit-rule.component.html b/src/portal/lib/src/create-edit-rule/create-edit-rule.component.html index c73ef837e..0d385fb79 100644 --- a/src/portal/lib/src/create-edit-rule/create-edit-rule.component.html +++ b/src/portal/lib/src/create-edit-rule/create-edit-rule.component.html @@ -31,7 +31,7 @@
- + @@ -126,15 +126,13 @@
- +
-
+
-
+
diff --git a/src/portal/lib/src/create-edit-rule/create-edit-rule.component.spec.ts b/src/portal/lib/src/create-edit-rule/create-edit-rule.component.spec.ts index e25de7eef..04dff182b 100644 --- a/src/portal/lib/src/create-edit-rule/create-edit-rule.component.spec.ts +++ b/src/portal/lib/src/create-edit-rule/create-edit-rule.component.spec.ts @@ -17,7 +17,8 @@ import { ReplicationRule, ReplicationJob, Endpoint, - ReplicationJobItem + ReplicationJobItem, + Adapter } from "../service/interface"; import { ErrorHandler } from "../error-handler/error-handler"; @@ -160,6 +161,38 @@ describe("CreateEditRuleComponent (inline template)", () => { deletion: false }; + let mockAdapter: Adapter = { + "type": "harbor", + "description": "", + "supported_resource_filters": [ + { + "type": "Name", + "style": "input" + }, + { + "type": "Version", + "style": "input" + }, + { + "type": "Label", + "style": "input" + }, + { + "type": "Resource", + "style": "radio", + "values": [ + "repository", + "chart" + ] + } + ], + "supported_triggers": [ + "Manual", + "Scheduled", + "EventBased" + ] + }; + let fixture: ComponentFixture; let fixtureCreate: ComponentFixture; @@ -173,10 +206,11 @@ describe("CreateEditRuleComponent (inline template)", () => { let spyOneRule: jasmine.Spy; let spyJobs: jasmine.Spy; + let spyAdapter: jasmine.Spy; let spyEndpoint: jasmine.Spy; let config: IServiceConfig = { - replicationBaseEndpoint: "/api/replication/executions/testing", + replicationBaseEndpoint: "/api/replication/testing", targetBaseEndpoint: "/api/registries/testing" }; @@ -230,6 +264,8 @@ describe("CreateEditRuleComponent (inline template)", () => { spyJobs = spyOn(replicationService, "getExecutions").and.returnValues( of(mockJob)); + spyAdapter = spyOn(replicationService, "getReplicationAdapter").and.returnValues( + of(mockAdapter)); spyEndpoint = spyOn(endpointService, "getEndpoints").and.returnValues( of(mockEndpoints) ); @@ -239,6 +275,7 @@ describe("CreateEditRuleComponent (inline template)", () => { it("Should open creation modal and load endpoints", async(() => { fixture.detectChanges(); + compCreate.initAdapter("harbor"); compCreate.openCreateEditRule(); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -254,6 +291,7 @@ describe("CreateEditRuleComponent (inline template)", () => { it("Should open modal to edit replication rule", async(() => { fixture.detectChanges(); + compCreate.initAdapter("harbor"); compCreate.openCreateEditRule(mockRule.id); fixture.whenStable().then(() => { fixture.detectChanges(); diff --git a/src/portal/lib/src/create-edit-rule/create-edit-rule.component.ts b/src/portal/lib/src/create-edit-rule/create-edit-rule.component.ts index beb220d5c..f86a856f3 100644 --- a/src/portal/lib/src/create-edit-rule/create-edit-rule.component.ts +++ b/src/portal/lib/src/create-edit-rule/create-edit-rule.component.ts @@ -21,7 +21,7 @@ import { EventEmitter, Output } from "@angular/core"; -import { Filter, ReplicationRule, Endpoint, Label } from "../service/interface"; +import { Filter, ReplicationRule, Endpoint, Label, Adapter } from "../service/interface"; import { Subject, Subscription } from "rxjs"; import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { FormArray, FormBuilder, FormGroup, Validators, FormControl } from "@angular/forms"; @@ -51,8 +51,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { selectedProjectList: Project[] = []; isFilterHide = false; weeklySchedule: boolean; - isScheduleOpt: boolean; - isImmediate = false; noProjectInfo = ""; noEndpointInfo = ""; isPushMode = true; @@ -60,7 +58,11 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { noSelectedEndpoint = true; filterCount = 0; alertClosed = false; - triggerNames: string[] = ["Manual", "Immediate", "Scheduled"]; + TRIGGER_TYPES = { + MANUAL: "Manual", + SCHEDULED: "Scheduled", + EVENT_BASED: "EventBased" + }; filterSelect: string[] = ["type", "repository", "tag", "label"]; ruleNameTooltip = "REPLICATION.NAME_TOOLTIP"; headerTitle = "REPLICATION.ADD_POLICY"; @@ -82,6 +84,8 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { formArrayLabel: FormArray; copyUpdateForm: ReplicationRule; cronString: string; + supportedTriggers: string[]; + supportedFilters: Filter[]; @Input() projectId: number; @Input() projectName: string; @@ -113,6 +117,13 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { }; } + initAdapter(type: string): void { + this.repService.getReplicationAdapter(type).subscribe(adapter => { + this.supportedFilters = adapter.supported_resource_filters; + this.supportedTriggers = adapter.supported_triggers; + }); + } + ngOnInit(): void { this.endpointService.getEndpoints().subscribe(endPoints => { this.targetList = endPoints || []; @@ -120,8 +131,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { }, error => { this.errorHandler.error(error); }); - - + this.initAdapter("harbor"); this.nameChecker .pipe(debounceTime(300)) .pipe(distinctUntilChanged()) @@ -148,18 +158,21 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { }); } + modeChange(): void { + if (this.isPushMode) { + this.initAdapter("harbor"); + } + } + sourceChange($event): void { - if ($event && $event.target) { - if ($event.target["value"] === "-1") { - this.noSelectedEndpoint = true; - return; - } - let selecedTarget: Endpoint = this.sourceList.find( - source => source.id === +$event.target["value"] - ); - this.noSelectedEndpoint = false; - } + this.noSelectedEndpoint = false; + let selectId = this.ruleForm.get('src_registry_id').value; + let selecedTarget: Endpoint = this.sourceList.find( + source => source.id === selectId + ); + + this.initAdapter(selecedTarget.type); } @@ -191,7 +204,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { dest_registry_id: new FormControl(), dest_namespace: "", trigger: this.fb.group({ - kind: this.triggerNames[0], + kind: '', schedule_param: this.fb.group({ cron: "" }) @@ -201,12 +214,24 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { }); } + selectTrigger($event: any): void { + + } + + isNotSchedule(): boolean { + return this.ruleForm.get("trigger").get("kind").value !== this.TRIGGER_TYPES.SCHEDULED; + } + + isNotEventBased(): boolean { + return this.ruleForm.get("trigger").get("kind").value !== this.TRIGGER_TYPES.EVENT_BASED; + } + initForm(): void { this.ruleForm.reset({ name: "", description: "", trigger: { - kind: this.triggerNames[0], + kind: this.supportedTriggers[0], schedule_param: { cron: "" } @@ -214,7 +239,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { deletion: false }); this.setFilter([]); - this.copyUpdateForm = clone(this.ruleForm.value); } @@ -439,26 +463,9 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { } } - selectTrigger($event: any): void { - if ($event && $event.target && $event.target["value"]) { - let val: string = $event.target["value"]; - if (val === this.triggerNames[2]) { - this.isScheduleOpt = true; - this.isImmediate = false; - } - if (val === this.triggerNames[1]) { - this.isScheduleOpt = false; - this.isImmediate = true; - } - if (val === this.triggerNames[0]) { - this.isScheduleOpt = false; - this.isImmediate = false; - } - } - } - // Replication Schedule select value exchange selectSchedule($event: any): void { + } checkRuleName(): void { @@ -532,7 +539,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { // add new Replication rule this.inProgress = true; let copyRuleForm: ReplicationRule = this.ruleForm.value; - copyRuleForm.trigger = null; if (this.isPushMode) { copyRuleForm.src_registry_id = null; } else { @@ -586,8 +592,6 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy { this.deletedLabelCount = 0; this.weeklySchedule = false; - this.isScheduleOpt = false; - this.isImmediate = false; this.policyId = -1; this.createEditRuleOpened = true; this.filterLabelInfo = []; diff --git a/src/portal/lib/src/endpoint/endpoint.component.spec.ts b/src/portal/lib/src/endpoint/endpoint.component.spec.ts index f871efba0..4522c84ed 100644 --- a/src/portal/lib/src/endpoint/endpoint.component.spec.ts +++ b/src/portal/lib/src/endpoint/endpoint.component.spec.ts @@ -93,13 +93,16 @@ describe("EndpointComponent (inline template)", () => { } ]; - let mockAdapter: [Adapter] = [{ + let mockAdapters: Adapter[] = [{ type: "Harbor", description: "test", - supported_resource_types: [ - "repository" + supported_resource_filters: [ + { + "type": "Name", + "style": "input" + } ], - supported_resource_filters: null + supported_triggers: [] }]; let comp: EndpointComponent; @@ -143,7 +146,7 @@ describe("EndpointComponent (inline template)", () => { ); spyAdapter = spyOn(endpointService, "getAdapters").and.returnValue( - of(mockAdapter) + of(mockAdapters) ); spyOnRules = spyOn( diff --git a/src/portal/lib/src/harbor-library.module.ts b/src/portal/lib/src/harbor-library.module.ts index b45098851..9c810c1a2 100644 --- a/src/portal/lib/src/harbor-library.module.ts +++ b/src/portal/lib/src/harbor-library.module.ts @@ -81,9 +81,8 @@ export const DefaultServiceConfig: IServiceConfig = { repositoryBaseEndpoint: "/api/repositories", logBaseEndpoint: "/api/logs", targetBaseEndpoint: "/api/registries", - replicationBaseEndpoint: "/api/replication/executions", + replicationBaseEndpoint: "/api/replication", replicationRuleEndpoint: "/api/replication/policies", - adapterEndpoint: "api/replication/adapters", vulnerabilityScanningBaseEndpoint: "/api/repositories", projectPolicyEndpoint: "/api/projects/configs", projectBaseEndpoint: "/api/projects", diff --git a/src/portal/lib/src/replication/replication.component.spec.ts b/src/portal/lib/src/replication/replication.component.spec.ts index 1bb6272df..9dcd83547 100644 --- a/src/portal/lib/src/replication/replication.component.spec.ts +++ b/src/portal/lib/src/replication/replication.component.spec.ts @@ -138,7 +138,7 @@ describe('Replication Component (inline template)', () => { let config: IServiceConfig = { replicationRuleEndpoint: '/api/policies/replication/testing', - replicationBaseEndpoint: '/api/replication/executions/testing' + replicationBaseEndpoint: '/api/replication/testing' }; beforeEach(async(() => { diff --git a/src/portal/lib/src/service.config.ts b/src/portal/lib/src/service.config.ts index 3a7547343..c82fd8ae4 100644 --- a/src/portal/lib/src/service.config.ts +++ b/src/portal/lib/src/service.config.ts @@ -54,11 +54,6 @@ export interface IServiceConfig { */ replicationBaseEndpoint?: string; - /** - * The base endpoint of the service used to handle the adapters. - */ - adapterEndpoint?: string; - /** * The base endpoint of the service used to handle the replication rules. * Replication rule related endpoints will be built based on this endpoint. diff --git a/src/portal/lib/src/service/interface.ts b/src/portal/lib/src/service/interface.ts index 12f999e71..1be26f8b7 100644 --- a/src/portal/lib/src/service/interface.ts +++ b/src/portal/lib/src/service/interface.ts @@ -87,15 +87,17 @@ export interface Endpoint extends Base { url: string; } +export interface Filter { + type: string; + style: string; + values ?: string[]; +} + export interface Adapter extends Base { type: string; description: string; - supported_resource_types: [ - string - ]; - supported_resource_filters: [ - string - ]; + supported_triggers: string []; + supported_resource_filters: Filter []; } /** diff --git a/src/portal/lib/src/service/job-log.service.spec.ts b/src/portal/lib/src/service/job-log.service.spec.ts index 7440d0276..9b4efadca 100644 --- a/src/portal/lib/src/service/job-log.service.spec.ts +++ b/src/portal/lib/src/service/job-log.service.spec.ts @@ -6,7 +6,7 @@ import { SERVICE_CONFIG, IServiceConfig } from '../service.config'; describe('JobLogService', () => { const mockConfig: IServiceConfig = { - replicationBaseEndpoint: "/api/replication/executions/testing", + replicationBaseEndpoint: "/api/replication/testing", scanJobEndpoint: "/api/jobs/scan/testing" }; @@ -33,7 +33,7 @@ describe('JobLogService', () => { it('should be initialized', inject([JobLogDefaultService], (service: JobLogService) => { expect(service).toBeTruthy(); - expect(config.replicationBaseEndpoint).toEqual("/api/replication/executions/testing"); + expect(config.replicationBaseEndpoint).toEqual("/api/replication/testing"); expect(config.scanJobEndpoint).toEqual("/api/jobs/scan/testing"); })); }); diff --git a/src/portal/lib/src/service/job-log.service.ts b/src/portal/lib/src/service/job-log.service.ts index 0114c05e2..f11ba6bd7 100644 --- a/src/portal/lib/src/service/job-log.service.ts +++ b/src/portal/lib/src/service/job-log.service.ts @@ -49,7 +49,7 @@ export class JobLogDefaultService extends JobLogService { super(); this._replicationJobBaseUrl = config.replicationBaseEndpoint ? config.replicationBaseEndpoint - : "/api/replication/executions"; + : "/api/replication"; this._scanningJobBaseUrl = config.scanJobEndpoint ? config.scanJobEndpoint : "/api/jobs/scan"; diff --git a/src/portal/lib/src/service/replication.service.spec.ts b/src/portal/lib/src/service/replication.service.spec.ts index 6c3fae9cc..030c3e5fb 100644 --- a/src/portal/lib/src/service/replication.service.spec.ts +++ b/src/portal/lib/src/service/replication.service.spec.ts @@ -7,7 +7,7 @@ import { SERVICE_CONFIG, IServiceConfig } from '../service.config'; describe('ReplicationService', () => { const mockConfig: IServiceConfig = { replicationRuleEndpoint: "/api/policies/replication/testing", - replicationBaseEndpoint: "/api/replication/executions/testing" + replicationBaseEndpoint: "/api/replication/testing" }; let config: IServiceConfig; @@ -38,6 +38,6 @@ describe('ReplicationService', () => { it('should inject the right config', () => { expect(config).toBeTruthy(); expect(config.replicationRuleEndpoint).toEqual("/api/policies/replication/testing"); - expect(config.replicationBaseEndpoint).toEqual("/api/replication/executions/testing"); + expect(config.replicationBaseEndpoint).toEqual("/api/replication/testing"); }); }); diff --git a/src/portal/lib/src/service/replication.service.ts b/src/portal/lib/src/service/replication.service.ts index 5f74b57e2..58f2e7a53 100644 --- a/src/portal/lib/src/service/replication.service.ts +++ b/src/portal/lib/src/service/replication.service.ts @@ -10,7 +10,8 @@ import { ReplicationJob, ReplicationRule, ReplicationJobItem, - ReplicationTasks + ReplicationTasks, + Adapter } from "./interface"; import { RequestQueryParams } from "./RequestQueryParams"; import { map, catchError } from "rxjs/operators"; @@ -140,6 +141,9 @@ export abstract class ReplicationService { ruleId: number | string ): Observable; + + abstract getReplicationAdapter(type: string): Observable; + /** * Get the jobs for the specified replication rule. * Set query parameters through 'queryParams', support: @@ -202,7 +206,7 @@ export class ReplicationDefaultService extends ReplicationService { : "/api/replication/policies"; this._replicateUrl = config.replicationBaseEndpoint ? config.replicationBaseEndpoint - : "/api/replication/executions"; + : "/api/replication"; } // Private methods @@ -218,6 +222,14 @@ export class ReplicationDefaultService extends ReplicationService { ); } + public getReplicationAdapter(type): Observable { + let requestUrl: string = `${this._replicateUrl}/adapters/${type}`; + return this.http + .get(requestUrl) + .pipe(map(response => response.json() as Adapter) + , catchError(error => observableThrowError(error))); + } + public getJobBaseUrl() { return this._replicateUrl; } diff --git a/src/portal/src/app/shared/shared.module.ts b/src/portal/src/app/shared/shared.module.ts index 23f3de670..1e0c46862 100644 --- a/src/portal/src/app/shared/shared.module.ts +++ b/src/portal/src/app/shared/shared.module.ts @@ -63,9 +63,8 @@ const uiLibConfig: IServiceConfig = { repositoryBaseEndpoint: "/api/repositories", logBaseEndpoint: "/api/logs", targetBaseEndpoint: "/api/registries", - replicationBaseEndpoint: "/api/replication/executions", + replicationBaseEndpoint: "/api/replication", replicationRuleEndpoint: "/api/replication/policies", - adapterEndpoint: "api/replication/adapters", vulnerabilityScanningBaseEndpoint: "/api/repositories", projectPolicyEndpoint: "/api/projects/configs", projectBaseEndpoint: "/api/projects",