From b799151c876e07425a8aed61507d2294578a2e1a Mon Sep 17 00:00:00 2001 From: ecaiyanlinux Date: Fri, 18 Jun 2021 10:41:57 +0200 Subject: [PATCH] Consumer service - List jobs without producer cherry-pick this commit from master branch Issue-ID: NONRTRIC-537 Signed-off-by: ychacon Change-Id: Ib38f5b12472f956243ccec6fff8fad4250247f98 Signed-off-by: ecaiyanlinux --- .../config/application-nonrtricgateway.yaml | 4 +- .../jobs-list/jobs-list.component.html | 12 +- .../jobs-list/jobs-list.component.spec.ts | 164 +++++++++------------ .../jobs-list/jobs-list.component.ts | 81 +++++----- webapp-frontend/src/app/interceptor.mock.ts | 48 +++++- .../src/app/interfaces/consumer.types.ts | 44 ++++++ .../src/app/interfaces/producer.types.ts | 10 +- webapp-frontend/src/app/mock/info-job1.json | 7 + webapp-frontend/src/app/mock/info-job2.json | 7 + webapp-frontend/src/app/mock/info-job3.json | 7 + webapp-frontend/src/app/mock/job1-status.json | 6 + webapp-frontend/src/app/mock/job2-status.json | 7 + webapp-frontend/src/app/mock/job3-status.json | 3 + webapp-frontend/src/app/mock/jobids.json | 5 + webapp-frontend/src/app/mock/jobs-producer1.json | 35 ----- webapp-frontend/src/app/mock/jobs-producer2.json | 24 --- webapp-frontend/src/app/mock/producer-status3.json | 3 + webapp-frontend/src/app/mock/producer3.json | 3 + webapp-frontend/src/app/mock/producerids.json | 3 +- .../src/app/services/ei/consumer.service.spec.ts | 108 ++++++++++++++ .../src/app/services/ei/consumer.service.ts | 64 ++++++++ .../src/app/services/ei/producer.service.spec.ts | 29 +--- .../src/app/services/ei/producer.service.ts | 7 +- 23 files changed, 431 insertions(+), 250 deletions(-) create mode 100644 webapp-frontend/src/app/interfaces/consumer.types.ts create mode 100644 webapp-frontend/src/app/mock/info-job1.json create mode 100644 webapp-frontend/src/app/mock/info-job2.json create mode 100644 webapp-frontend/src/app/mock/info-job3.json create mode 100644 webapp-frontend/src/app/mock/job1-status.json create mode 100644 webapp-frontend/src/app/mock/job2-status.json create mode 100644 webapp-frontend/src/app/mock/job3-status.json create mode 100644 webapp-frontend/src/app/mock/jobids.json delete mode 100644 webapp-frontend/src/app/mock/jobs-producer1.json delete mode 100644 webapp-frontend/src/app/mock/jobs-producer2.json create mode 100644 webapp-frontend/src/app/mock/producer-status3.json create mode 100644 webapp-frontend/src/app/mock/producer3.json create mode 100644 webapp-frontend/src/app/services/ei/consumer.service.spec.ts create mode 100644 webapp-frontend/src/app/services/ei/consumer.service.ts diff --git a/docker-compose/nonrtric-gateway/config/application-nonrtricgateway.yaml b/docker-compose/nonrtric-gateway/config/application-nonrtricgateway.yaml index fb8c106..cee5398 100644 --- a/docker-compose/nonrtric-gateway/config/application-nonrtricgateway.yaml +++ b/docker-compose/nonrtric-gateway/config/application-nonrtricgateway.yaml @@ -27,11 +27,11 @@ spring: wiretap: true routes: - id: A1-Policy - uri: https://localhost:8433 + uri: https://policy-agent:8433 predicates: - Path=/a1-policy/** - id: A1-EI - uri: https://localhost:8434 + uri: https://ecs:8434 predicates: - Path=/data-producer/**,/data-consumer/** management: diff --git a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.html b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.html index aca0931..d2d8bf9 100644 --- a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.html +++ b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.html @@ -38,18 +38,18 @@ limitations under the License. {{job.jobId}} - +
- - Producer ID + + Producers
- {{job.prodId}} + {{job.prodIds}}
@@ -90,8 +90,8 @@ limitations under the License. {{job.targetUri}} - - + + diff --git a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.spec.ts b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.spec.ts index f5021df..6e815af 100644 --- a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.spec.ts +++ b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.spec.ts @@ -41,56 +41,41 @@ import { MatTableModule } from "@angular/material/table"; import { MatTableHarness } from "@angular/material/table/testing"; import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; import { of } from "rxjs/observable/of"; -import { JobInfo } from "@interfaces/producer.types"; -import { ProducerService } from "@services/ei/producer.service"; +import { ConsumerStatus, JobInfo } from "@interfaces/consumer.types"; import { UiService } from "@services/ui/ui.service"; import { Job, JobsListComponent } from "./jobs-list.component"; import { Subscription } from "rxjs"; +import { ConsumerService } from "@services/ei/consumer.service"; let component: JobsListComponent; let fixture: ComponentFixture; const jobInfo1 = { - info_job_identity: "job1", - info_type_identity: "type1", - owner: "owner1", - target_uri: "http://one", -} as JobInfo; -const jobInfo2 = { - info_job_identity: "job2", - info_type_identity: "type2", - owner: "owner2", - target_uri: "http://two", + info_type_id: "type1", + job_owner: "owner1", + job_result_uri: "http://one", + job_definition: {}, } as JobInfo; +const jobStatus1 = { + info_job_status: "ENABLED", + producers: ["producer1"], +} as ConsumerStatus; + const job1 = { jobId: "job1", typeId: "type1", owner: "owner1", targetUri: "http://one", - prodId: "producer1", + prodIds: ["producer1"], } as Job; const job2 = { jobId: "job2", - typeId: "type2", - owner: "owner2", - targetUri: "http://two", - prodId: "producer1", -} as Job; -const job3 = { - jobId: "job1", typeId: "type1", owner: "owner1", targetUri: "http://one", - prodId: "producer2", -} as Job; -const job4 = { - jobId: "job2", - typeId: "type2", - owner: "owner2", - targetUri: "http://two", - prodId: "producer2", + prodIds: ["producer1"], } as Job; describe("JobsListComponent", () => { @@ -98,8 +83,9 @@ describe("JobsListComponent", () => { beforeEach(async(() => { const spy = jasmine.createSpyObj("EIService", [ - "getProducerIds", - "getJobsForProducer", + "getJobIds", + "getJobInfo", + "getConsumerStatus", ]); TestBed.configureTestingModule({ @@ -115,7 +101,7 @@ describe("JobsListComponent", () => { ], schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [JobsListComponent], - providers: [{ provide: ProducerService, useValue: spy }, UiService], + providers: [{ provide: ConsumerService, useValue: spy }, UiService], }) .compileComponents() .then(() => { @@ -127,7 +113,7 @@ describe("JobsListComponent", () => { const expectedJob1Row = { jobId: "job1", - prodId: "producer1", + prodIds: "producer1", typeId: "type1", owner: "owner1", targetUri: "http://one", @@ -144,8 +130,8 @@ describe("JobsListComponent", () => { tick(0); const actualJobs: Job[] = component.jobs(); - expect(actualJobs.length).toEqual(4); - expect(actualJobs).toEqual([job1, job2, job3, job4]); + expect(actualJobs.length).toEqual(2); + expect(actualJobs).toEqual([job1, job2]); newSub.unsubscribe(); })); @@ -161,7 +147,7 @@ describe("JobsListComponent", () => { headerRow[0].getCellTextByColumnName().then((header) => { expect(header).toEqual({ jobId: "Job ID", - prodId: "Producer ID", + prodIds: "Producers", typeId: "Type ID", owner: "Owner", targetUri: "Target URI", @@ -198,32 +184,18 @@ describe("JobsListComponent", () => { expectedJob1Row, { jobId: "job2", - prodId: "producer1", - typeId: "type2", - owner: "owner2", - targetUri: "http://two", - }, - { - jobId: "job1", - prodId: "producer2", + prodIds: "producer1", typeId: "type1", owner: "owner1", targetUri: "http://one", }, - { - jobId: "job2", - prodId: "producer2", - typeId: "type2", - owner: "owner2", - targetUri: "http://two", - }, ]; loader .getHarness(MatTableHarness.with({ selector: "#jobsTable" })) .then((loadTable) => { loadTable.getRows().then((jobRows) => { - expect(jobRows.length).toEqual(4); + expect(jobRows.length).toEqual(2); jobRows.forEach((row) => { row.getCellTextByColumnName().then((values) => { expect(expectedJobRows).toContain( @@ -238,26 +210,32 @@ describe("JobsListComponent", () => { it("should display default values for non required properties ", fakeAsync(() => { const jobMissingProperties = { - info_job_identity: "job1", - info_job_data: { + job_definition: { jobparam2: "value2_job2", jobparam3: "value3_job2", jobparam1: "value1_job2", }, - target_uri: "http://one", + job_result_uri: "http://one", } as JobInfo; - - let producerServiceSpy = TestBed.inject(ProducerService) as jasmine.SpyObj; - producerServiceSpy.getProducerIds.and.returnValue(of(["producer1"])); - producerServiceSpy.getJobsForProducer.and.returnValue( - of([jobMissingProperties]) + const jobMissingPropertiesStatus = { + info_job_status: "ENABLED", + producers: ["producer1"], + } as ConsumerStatus; + + let consumerServiceSpy = TestBed.inject( + ConsumerService + ) as jasmine.SpyObj; + consumerServiceSpy.getJobIds.and.returnValue(of(["job1"])); + consumerServiceSpy.getJobInfo.and.returnValue(of(jobMissingProperties)); + consumerServiceSpy.getConsumerStatus.and.returnValue( + of(jobMissingPropertiesStatus) ); component.ngOnInit(); tick(0); const expectedJobRow = { jobId: "job1", - prodId: "producer1", + prodIds: "producer1", typeId: "< No type >", owner: "< No owner >", targetUri: "http://one", @@ -290,7 +268,7 @@ describe("JobsListComponent", () => { idFilter.setValue("1").then((_) => { tick(10); loadTable.getRows().then((jobRows) => { - expect(jobRows.length).toEqual(2); + expect(jobRows.length).toEqual(1); jobRows[0].getCellTextByColumnName().then((value) => { expect(expectedJob1Row).toEqual( jasmine.objectContaining(value) @@ -440,8 +418,8 @@ describe("JobsListComponent", () => { it("should not sort when clicking on filtering box", fakeAsync(() => { const expectedJobRow = { - jobId: "job1", - prodId: "producer2", + jobId: "job2", + prodIds: "producer1", typeId: "type1", owner: "owner1", targetUri: "http://one", @@ -460,8 +438,8 @@ describe("JobsListComponent", () => { tick(10); idFilter.setValue("").then((_) => { loadTable.getRows().then((jobRows) => { - expect(jobRows.length).toEqual(4); - jobRows[2].getCellTextByColumnName().then((value) => { + expect(jobRows.length).toEqual(2); + jobRows[1].getCellTextByColumnName().then((value) => { expect(expectedJobRow).toEqual( jasmine.objectContaining(value) ); @@ -477,8 +455,8 @@ describe("JobsListComponent", () => { tick(10); typeIdFilter.setValue("").then((_) => { loadTable.getRows().then((jobRows) => { - expect(jobRows.length).toEqual(4); - jobRows[2].getCellTextByColumnName().then((value) => { + expect(jobRows.length).toEqual(2); + jobRows[1].getCellTextByColumnName().then((value) => { expect(expectedJobRow).toEqual( jasmine.objectContaining(value) ); @@ -492,8 +470,8 @@ describe("JobsListComponent", () => { tick(10); ownerFilter.setValue("").then((_) => { loadTable.getRows().then((jobRows) => { - expect(jobRows.length).toEqual(4); - jobRows[2].getCellTextByColumnName().then((value) => { + expect(jobRows.length).toEqual(2); + jobRows[1].getCellTextByColumnName().then((value) => { expect(expectedJobRow).toEqual( jasmine.objectContaining(value) ); @@ -509,8 +487,8 @@ describe("JobsListComponent", () => { tick(10); targetUriFilter.setValue("").then((_) => { loadTable.getRows().then((jobRows) => { - expect(jobRows.length).toEqual(4); - jobRows[2].getCellTextByColumnName().then((value) => { + expect(jobRows.length).toEqual(2); + jobRows[1].getCellTextByColumnName().then((value) => { expect(expectedJobRow).toEqual( jasmine.objectContaining(value) ); @@ -525,52 +503,56 @@ describe("JobsListComponent", () => { describe("#paging", () => { it("should work properly on the table", fakeAsync(() => { - let producerServiceSpy = TestBed.inject( - ProducerService - ) as jasmine.SpyObj; - producerServiceSpy.getProducerIds.and.returnValue( - of(["producer1", "producer2"]) - ); - producerServiceSpy.getJobsForProducer.and.returnValue( - of([jobInfo1, jobInfo2, jobInfo1]) + let consumerServiceSpy = TestBed.inject( + ConsumerService + ) as jasmine.SpyObj; + consumerServiceSpy.getJobIds.and.returnValue( + of(["job1", "job2", "job3", "job4", "job5", "job6", "job7"]) ); - tick(0); + consumerServiceSpy.getJobInfo.and.returnValue(of(jobInfo1)); + consumerServiceSpy.getConsumerStatus.and.returnValue(of(jobStatus1)); + component.ngOnInit(); + tick(); loader.getHarness(MatPaginatorHarness).then((paging) => { paging.setPageSize(5); - + tick(1000); loader .getHarness(MatTableHarness.with({ selector: "#jobsTable" })) .then((loadTable) => { loadTable.getRows().then((jobRows) => { expect(jobRows.length).toEqual(5); }); + paging.goToNextPage(); + tick(1000); + loadTable.getRows().then((jobRows) => { - expect(jobRows.length).toEqual(1); + expect(jobRows.length).toEqual(2); jobRows[0].getCellTextByColumnName().then((value) => { const expectedRow = { - jobId: "job1", - prodId: "producer2", + jobId: "job6", + prodIds: "producer1", typeId: "type1", owner: "owner1", targetUri: "http://one", }; - expect(expectedRow).toContain( - jasmine.objectContaining(value) - ); + discardPeriodicTasks(); + expect(expectedRow).toEqual(jasmine.objectContaining(value)); }); }); }); }); - discardPeriodicTasks(); })); }); }); }); function setServiceSpy() { - let producerServiceSpy = TestBed.inject(ProducerService) as jasmine.SpyObj; - producerServiceSpy.getProducerIds.and.returnValue(of(["producer1", "producer2"])); - producerServiceSpy.getJobsForProducer.and.returnValue(of([jobInfo1, jobInfo2])); + let consumerServiceSpy = TestBed.inject( + ConsumerService + ) as jasmine.SpyObj; + consumerServiceSpy.getJobIds.and.returnValue(of(["job1", "job2"])); + consumerServiceSpy.getJobInfo.and.returnValue(of(jobInfo1)); + consumerServiceSpy.getConsumerStatus.and.returnValue(of(jobStatus1)); } diff --git a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.ts b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.ts index f06202c..43b3ad8 100644 --- a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.ts +++ b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.ts @@ -22,20 +22,18 @@ import { FormControl, FormGroup } from "@angular/forms"; import { MatPaginator } from "@angular/material/paginator"; import { Sort } from "@angular/material/sort"; import { MatTableDataSource } from "@angular/material/table"; -import { EMPTY, forkJoin, Subscription, timer } from "rxjs"; +import { EMPTY, forkJoin, of, Subscription, timer } from "rxjs"; import { BehaviorSubject } from "rxjs/BehaviorSubject"; import { mergeMap, finalize, map, tap, switchMap } from "rxjs/operators"; -import { JobInfo } from "@interfaces/producer.types"; -import { ProducerService } from "@services/ei/producer.service"; +import { ConsumerService } from "@services/ei/consumer.service"; import { UiService } from "@services/ui/ui.service"; export interface Job { jobId: string; - jobData: any; typeId: string; targetUri: string; owner: string; - prodId: string; + prodIds: string[]; } @Component({ @@ -58,13 +56,13 @@ export class JobsListComponent implements OnInit { checked: boolean = false; firstTime: boolean = true; - constructor(private producerService: ProducerService, private ui: UiService) { + constructor(private consumerService: ConsumerService, private ui: UiService) { this.jobForm = new FormGroup({ jobId: new FormControl(""), typeId: new FormControl(""), owner: new FormControl(""), targetUri: new FormControl(""), - prodId: new FormControl(""), + prodIds: new FormControl(""), }); } @@ -82,7 +80,7 @@ export class JobsListComponent implements OnInit { this.isDataIncluding(data.jobId, searchTerms.jobId) && this.isDataIncluding(data.owner, searchTerms.owner) && this.isDataIncluding(data.typeId, searchTerms.typeId) && - this.isDataIncluding(data.prodId, searchTerms.prodId) + this.isArrayIncluding(data.prodIds, searchTerms.prodIds) ); }) as (data: Job, filter: any) => boolean; }); @@ -97,11 +95,15 @@ export class JobsListComponent implements OnInit { } dataSubscription(): Subscription { - let prodId = []; - const jobs$ = this.producerService.getProducerIds().pipe( - tap((data) => (prodId = data)), - mergeMap((prodIds) => - forkJoin(prodIds.map((id) => this.producerService.getJobsForProducer(id))) + const jobsInfo$ = this.consumerService.getJobIds().pipe( + mergeMap((jobIds) => + forkJoin(jobIds.map((jobId) => { + return forkJoin([ + of(jobId), + this.consumerService.getJobInfo(jobId), + this.consumerService.getConsumerStatus(jobId) + ]) + })) ), finalize(() => this.loadingSubject$.next(false)) ); @@ -112,8 +114,8 @@ export class JobsListComponent implements OnInit { tap((_) => { this.loadingSubject$.next(true); }), - switchMap((_) => jobs$), - map((response) => this.extractJobs(prodId, response)) + switchMap((_) => jobsInfo$), + map((response) => this.extractJobs(response)) ) ) ); @@ -137,7 +139,7 @@ export class JobsListComponent implements OnInit { this.jobForm.get("typeId").setValue(""); this.jobForm.get("owner").setValue(""); this.jobForm.get("targetUri").setValue(""); - this.jobForm.get("prodId").setValue(""); + this.jobForm.get("prodIds").setValue(""); } sortJobs(sort: Sort) { @@ -153,8 +155,8 @@ export class JobsListComponent implements OnInit { return this.compare(a.owner, b.owner, isAsc); case "targetUri": return this.compare(a.targetUri, b.targetUri, isAsc); - case "prodId": - return this.compare(a.prodId, b.prodId, isAsc); + case "prodIds": + return this.compare(a.prodIds, b.prodIds, isAsc); default: return 0; } @@ -180,6 +182,14 @@ export class JobsListComponent implements OnInit { return data.toLowerCase().includes(transformedFilter); } + isArrayIncluding(data: string[], filter: string): boolean { + if(!data) + return true; + for (let i = 0; i < data.length; i++) { + return this.isDataIncluding(data[i], filter); + } + } + getJobTypeId(job: Job): string { if (job.typeId) { return job.typeId; @@ -198,13 +208,19 @@ export class JobsListComponent implements OnInit { return this.jobsSubject$.value; } - private extractJobs(prodId: number[], res: JobInfo[][]) { + private extractJobs(res: any) { this.clearFilter(); let jobList = []; - prodId.forEach((element, index) => { - let jobs = res[index]; - jobList = jobList.concat(jobs.map((job) => this.createJob(element, job))); - }); + res.forEach(element => { + let jobObj = {}; + jobObj.jobId = element[0]; + jobObj.owner = element[1].job_owner; + jobObj.targetUri = element[1].job_result_uri; + jobObj.typeId = element[1].info_type_id; + jobObj.prodIds = (element[2].producers) ? element[2].producers : ["No Producers"]; + jobList = jobList.concat(jobObj); + }); + this.jobsSubject$.next(jobList); if (this.firstTime && jobList.length > 0) { this.polling$.next(jobList.length); @@ -213,25 +229,6 @@ export class JobsListComponent implements OnInit { return jobList; } - createJobList(prodId: any[], result: JobInfo[][]) { - let jobList = []; - prodId.forEach((element, index) => { - let jobs = result[index]; - jobList = jobList.concat(jobs.map((job) => this.createJob(element, job))); - }); - return jobList; - } - - createJob(element: any, job: JobInfo): any { - let infoJob = {}; - infoJob.jobId = job.info_job_identity; - infoJob.typeId = job.info_type_identity; - infoJob.owner = job.owner; - infoJob.targetUri = job.target_uri; - infoJob.prodId = element; - return infoJob; - } - refreshDataClick() { this.refresh$.next(""); } diff --git a/webapp-frontend/src/app/interceptor.mock.ts b/webapp-frontend/src/app/interceptor.mock.ts index b0603c9..d40a0fc 100644 --- a/webapp-frontend/src/app/interceptor.mock.ts +++ b/webapp-frontend/src/app/interceptor.mock.ts @@ -35,23 +35,31 @@ import * as policyinstance2 from "./mock/policy-instance-2.json"; import * as noTypePolicyinstance from "./mock/policy-instance-notype.json"; import * as policyinstance1Status from "./mock/policy-instance-1-status.json"; import * as policyinstance2Status from "./mock/policy-instance-2-status.json"; -import * as jobsProd1 from "./mock/jobs-producer1.json"; -import * as jobsProd2 from "./mock/jobs-producer2.json"; import * as producerIds from "./mock/producerids.json"; import * as producer1 from "./mock/producer1.json"; import * as producer2 from "./mock/producer2.json"; +import * as producer3 from "./mock/producer3.json"; import * as producerstatus1 from "./mock/producer-status1.json"; import * as producerstatus2 from "./mock/producer-status2.json"; +import * as producerstatus3 from "./mock/producer-status3.json"; import * as policytypes1 from "./mock/policy-type1.json"; import * as policytypes0 from "./mock/policy-type0.json"; import * as policyinstanceedit from "./mock/policy-instance-edit.json"; import * as ric1 from "./mock/ric1.json"; import * as ric2 from "./mock/ric2.json"; import * as ricconfig from "./mock/ric-configuration.json"; +import * as jobIds from "./mock/jobids.json"; +import * as infoJob1 from "./mock/info-job1.json"; +import * as infoJob2 from "./mock/info-job2.json"; +import * as infoJob3 from "./mock/info-job3.json"; +import * as job1Status from "./mock/job1-status.json"; +import * as job2Status from "./mock/job2-status.json"; +import * as job3Status from "./mock/job3-status.json"; import { delay } from "rxjs/operators"; const POLICY_PATH = "/a1-policy/v2" const INFO_PATH = "/data-producer/v1" +const CONSUMER_PATH = "/data-consumer/v1" const urls = [ { @@ -142,6 +150,10 @@ const urls = [ url: INFO_PATH + "/info-producers/producer2", json: producer2, }, + { + url: INFO_PATH + "/info-producers/producer3", + json: producer3, + }, { url: INFO_PATH + "/info-producers/producer1/status", json: producerstatus1, @@ -151,12 +163,36 @@ const urls = [ json: producerstatus2, }, { - url: INFO_PATH + "/info-producers/producer1/info-jobs", - json: jobsProd1, + url: INFO_PATH + "/info-producers/producer3/status", + json: producerstatus3, + }, + { + url: CONSUMER_PATH + "/info-jobs", + json: jobIds, + }, + { + url: CONSUMER_PATH + "/info-jobs/job1", + json: infoJob1, + }, + { + url: CONSUMER_PATH + "/info-jobs/job2", + json: infoJob2, + }, + { + url: CONSUMER_PATH + "/info-jobs/job3", + json: infoJob3, + }, + { + url: CONSUMER_PATH + "/info-jobs/job1/status", + json: job1Status, + }, + { + url: CONSUMER_PATH + "/info-jobs/job2/status", + json: job2Status, }, { - url: INFO_PATH + "/info-producers/producer2/info-jobs", - json: jobsProd2, + url: CONSUMER_PATH + "/info-jobs/job3/status", + json: job3Status, }, { url: '/a1-policy/v2/configuration', diff --git a/webapp-frontend/src/app/interfaces/consumer.types.ts b/webapp-frontend/src/app/interfaces/consumer.types.ts new file mode 100644 index 0000000..7a81385 --- /dev/null +++ b/webapp-frontend/src/app/interfaces/consumer.types.ts @@ -0,0 +1,44 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2020 Nordix Foundation + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================LICENSE_END=================================== + */ + +// Models of data used by the EI Coordinator + +export interface JobInfo { + info_type_id: string; + job_definition: any; + job_result_uri: string; + job_owner: string; + status_notification_uri: string; +} + +export interface Consumer { + consumer_id: string; + status: string; +} + +export enum OperationalState { + ENABLED = 'ENABLED', + DISABLED = 'DISABLED' +} + +export interface ConsumerStatus { + info_job_status: OperationalState; + producers: string[]; +} \ No newline at end of file diff --git a/webapp-frontend/src/app/interfaces/producer.types.ts b/webapp-frontend/src/app/interfaces/producer.types.ts index 1e80fdf..1b548da 100644 --- a/webapp-frontend/src/app/interfaces/producer.types.ts +++ b/webapp-frontend/src/app/interfaces/producer.types.ts @@ -20,14 +20,6 @@ // Models of data used by the EI Coordinator -export interface JobInfo { - info_job_identity: string; - info_job_data: any; - info_type_identity: string; - target_uri: string; - owner: string; -} - export interface Producer { producer_id: string; producer_types: string[]; @@ -44,4 +36,4 @@ export enum OperationalState { } export interface ProducerStatus { operational_state: OperationalState -} \ No newline at end of file +} diff --git a/webapp-frontend/src/app/mock/info-job1.json b/webapp-frontend/src/app/mock/info-job1.json new file mode 100644 index 0000000..50492de --- /dev/null +++ b/webapp-frontend/src/app/mock/info-job1.json @@ -0,0 +1,7 @@ +{ + "info_type_id": "type1", + "job_owner": "ricsim_g3_2", + "job_definition": {}, + "job_result_uri": "https://ricsim_g3_1:8185/datadelivery", + "status_notification_uri": "http://producer:80/" +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/info-job2.json b/webapp-frontend/src/app/mock/info-job2.json new file mode 100644 index 0000000..3e810a6 --- /dev/null +++ b/webapp-frontend/src/app/mock/info-job2.json @@ -0,0 +1,7 @@ +{ + "info_type_id": "type2", + "job_owner": "ricsim_g3_1", + "job_definition": {}, + "job_result_uri": "https://ricsim_g3_1:8185/datadelivery", + "status_notification_uri": "http://producer:80/" +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/info-job3.json b/webapp-frontend/src/app/mock/info-job3.json new file mode 100644 index 0000000..19fc1ac --- /dev/null +++ b/webapp-frontend/src/app/mock/info-job3.json @@ -0,0 +1,7 @@ +{ + "info_type_id": "type5", + "job_owner": "ricsim_g3_5", + "job_definition": {}, + "job_result_uri": "https://ricsim_g3_5:8185/datadelivery", + "status_notification_uri": "http://producer:80/" +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/job1-status.json b/webapp-frontend/src/app/mock/job1-status.json new file mode 100644 index 0000000..23b96b8 --- /dev/null +++ b/webapp-frontend/src/app/mock/job1-status.json @@ -0,0 +1,6 @@ +{ + "info_job_status": "DISABLED", + "producers": [ + "producer3" + ] +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/job2-status.json b/webapp-frontend/src/app/mock/job2-status.json new file mode 100644 index 0000000..af73a47 --- /dev/null +++ b/webapp-frontend/src/app/mock/job2-status.json @@ -0,0 +1,7 @@ +{ + "info_job_status": "ENABLED", + "producers": [ + "producer1", + "producer2" + ] +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/job3-status.json b/webapp-frontend/src/app/mock/job3-status.json new file mode 100644 index 0000000..b2015c0 --- /dev/null +++ b/webapp-frontend/src/app/mock/job3-status.json @@ -0,0 +1,3 @@ +{ + "info_job_status": "ENABLED" +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/jobids.json b/webapp-frontend/src/app/mock/jobids.json new file mode 100644 index 0000000..9b33b55 --- /dev/null +++ b/webapp-frontend/src/app/mock/jobids.json @@ -0,0 +1,5 @@ +[ + "job1", + "job2", + "job3" +] \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/jobs-producer1.json b/webapp-frontend/src/app/mock/jobs-producer1.json deleted file mode 100644 index 746add9..0000000 --- a/webapp-frontend/src/app/mock/jobs-producer1.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "info_job_identity": "job1", - "info_type_identity": "type1", - "owner": "owner1", - "info_job_data": { - "jobparam2": "value2_job1", - "jobparam3": "value3_job1", - "jobparam1": "value1_job1" - }, - "target_uri": "https://ricsim_g1_1:8185/datadelivery" - }, - { - "info_job_identity": "job2", - "info_type_identity": "type1", - "owner": "owner2", - "info_job_data": { - "jobparam2": "value2_job2", - "jobparam3": "value3_job2", - "jobparam1": "value1_job2" - }, - "target_uri": "https://ricsim_g2_1:8185/datadelivery" - }, - { - "info_job_identity": "job4", - "info_type_identity": "type1", - "owner": "owner3", - "info_job_data": { - "jobparam2": "value2_job2", - "jobparam3": "value3_job2", - "jobparam1": "value1_job2" - }, - "target_uri": "https://ricsim_g3_1:8185/datadelivery" - } - ] \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/jobs-producer2.json b/webapp-frontend/src/app/mock/jobs-producer2.json deleted file mode 100644 index bb4fe01..0000000 --- a/webapp-frontend/src/app/mock/jobs-producer2.json +++ /dev/null @@ -1,24 +0,0 @@ -[ - { - "info_job_identity": "job3", - "info_type_identity": "type2", - "owner": "owner1", - "info_job_data": { - "jobparam2": "value2_job3", - "jobparam3": "value3_job3", - "jobparam1": "value1_job3" - }, - "target_uri": "https://ricsim_g3_1:8185/datadelivery" - }, - { - "info_job_identity": "job5", - "info_type_identity": "type2", - "owner": "owner5", - "info_job_data": { - "jobparam2": "value2_job2", - "jobparam3": "value3_job2", - "jobparam1": "value1_job2" - }, - "target_uri": "https://ricsim_g3_1:8185/datadelivery" - } - ] \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/producer-status3.json b/webapp-frontend/src/app/mock/producer-status3.json new file mode 100644 index 0000000..a487293 --- /dev/null +++ b/webapp-frontend/src/app/mock/producer-status3.json @@ -0,0 +1,3 @@ +{ + "operational_state": "ENABLED" +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/producer3.json b/webapp-frontend/src/app/mock/producer3.json new file mode 100644 index 0000000..3eda758 --- /dev/null +++ b/webapp-frontend/src/app/mock/producer3.json @@ -0,0 +1,3 @@ +{ + "supported_info_types": [ "type1"] +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/producerids.json b/webapp-frontend/src/app/mock/producerids.json index c6789c0..86232c6 100644 --- a/webapp-frontend/src/app/mock/producerids.json +++ b/webapp-frontend/src/app/mock/producerids.json @@ -1,4 +1,5 @@ [ "producer1", - "producer2" + "producer2", + "producer3" ] \ No newline at end of file diff --git a/webapp-frontend/src/app/services/ei/consumer.service.spec.ts b/webapp-frontend/src/app/services/ei/consumer.service.spec.ts new file mode 100644 index 0000000..352e1e3 --- /dev/null +++ b/webapp-frontend/src/app/services/ei/consumer.service.spec.ts @@ -0,0 +1,108 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2019 Nordix Foundation + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================LICENSE_END=================================== + */ +import { ConsumerService } from "./consumer.service"; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; +import { JobInfo, ConsumerStatus, OperationalState } from '@app/interfaces/consumer.types'; + +describe('ConsumerService', () => { + let basePath = '/data-consumer/v1'; + let service: ConsumerService; + let httpTestingController: HttpTestingController; + let expectedEIJobs: string[]; + let expectedConsumerStatus: ConsumerStatus; + let expectedJobInfo: JobInfo; + + beforeEach(() => TestBed.configureTestingModule({ + imports: [ + HttpClientTestingModule + ], + providers: [ + ConsumerService + ] + })); + + beforeEach(() => { + service = TestBed.inject(ConsumerService); + httpTestingController = TestBed.inject(HttpTestingController); + expectedEIJobs = ['job1', 'job2']; + expectedConsumerStatus = { + info_job_status: OperationalState.ENABLED, + producers: [ + 'producer1' + ] + } + expectedJobInfo = { + job_definition: 'data', + info_type_id: 'type1', + job_result_uri: 'uri', + job_owner: 'owner1', + status_notification_uri: 'status_uri' + } + }) + + it('should be created', () => { + service = TestBed.inject(ConsumerService); + expect(service).toBeTruthy(); + }); + + it('should get all the jobs ids', () => { + service.getJobIds().subscribe( + jobs => expect(jobs).toEqual(expectedEIJobs, 'should return expected Jobs'), + fail + ); + + const req = httpTestingController.expectOne(basePath + '/' + service.jobsPath); + expect(req.request.method).toEqual('GET'); + + req.flush(expectedEIJobs); //Return expected jobs ids + + httpTestingController.verify(); + }); + + + it('should return consumer status', () => { + service.getConsumerStatus('job1').subscribe( + consumerStatus => expect(consumerStatus).toEqual(expectedConsumerStatus, 'should return expected status'), + fail + ); + + const req = httpTestingController.expectOne(basePath + '/' + service.jobsPath + '/job1/' + service.consumerStatusPath); + expect(req.request.method).toEqual('GET'); + + req.flush(expectedConsumerStatus); //Return expected status + + httpTestingController.verify(); + }); + + it('should return the job info', () => { + service.getJobInfo('job1').subscribe( + jobInfo => expect(jobInfo).toEqual(expectedJobInfo, 'should return expected job info'), + fail + ); + + const req = httpTestingController.expectOne(basePath + '/' + service.jobsPath + '/job1'); + expect(req.request.method).toEqual('GET'); + + req.flush(expectedJobInfo); //Return expected job info + + httpTestingController.verify(); + }); +}); \ No newline at end of file diff --git a/webapp-frontend/src/app/services/ei/consumer.service.ts b/webapp-frontend/src/app/services/ei/consumer.service.ts new file mode 100644 index 0000000..19ec3cb --- /dev/null +++ b/webapp-frontend/src/app/services/ei/consumer.service.ts @@ -0,0 +1,64 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2019 Nordix Foundation + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================LICENSE_END=================================== + */ + +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { ConsumerStatus, JobInfo } from '@interfaces/consumer.types'; + +/** + * Services for calling the EI endpoints. + */ +@Injectable({ + providedIn: 'root' +}) +export class ConsumerService { + + private basePath = '/data-consumer/v1'; + readonly jobsPath = 'info-jobs'; + readonly consumerStatusPath = 'status'; + + private buildPath(...args: any[]) { + let result = this.basePath; + args.forEach(part => { + result = result + '/' + part; + }); + return result; + } + + constructor(private httpClient: HttpClient) { + // injects to variable httpClient + } + + getJobIds(): Observable { + const url = this.buildPath(this.jobsPath); + return this.httpClient.get(url); + } + + getJobInfo(infoJobId: string): Observable { + const url = this.buildPath(this.jobsPath, infoJobId); + return this.httpClient.get(url); + } + + getConsumerStatus(infoJobId: string): Observable { + const url = this.buildPath(this.jobsPath, infoJobId, this.consumerStatusPath); + return this.httpClient.get(url); + } +} diff --git a/webapp-frontend/src/app/services/ei/producer.service.spec.ts b/webapp-frontend/src/app/services/ei/producer.service.spec.ts index 61ba253..a5562ee 100644 --- a/webapp-frontend/src/app/services/ei/producer.service.spec.ts +++ b/webapp-frontend/src/app/services/ei/producer.service.spec.ts @@ -20,7 +20,7 @@ import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing' import { TestBed } from '@angular/core/testing'; -import { JobInfo, ProducerStatus, OperationalState, ProducerRegistrationInfo } from '@interfaces/producer.types'; +import { ProducerStatus, OperationalState, ProducerRegistrationInfo } from '@interfaces/producer.types'; import { ProducerService } from './producer.service'; describe('ProducerService', () => { @@ -66,33 +66,6 @@ describe('ProducerService', () => { }); }); - describe('#getJobsForProducer', () => { - let expectedEIJobs: JobInfo[]; - - beforeEach(() => { - service = TestBed.inject(ProducerService); - httpTestingController = TestBed.inject(HttpTestingController); - expectedEIJobs = [ - { info_job_identity: '1', info_job_data: 'data', info_type_identity: 'Type ID 1', target_uri: 'hhtp://url', owner: 'owner'}, - { info_job_identity: '2', info_job_data: 'EI Job 2', info_type_identity: 'Type ID 2', target_uri: 'hhtp://url', owner: 'owner'} - ] as JobInfo[]; - }); - - it('should return all jobs', () => { - service.getJobsForProducer('producer1').subscribe( - jobs => expect(jobs).toEqual(expectedEIJobs, 'should return expected Jobs'), - fail - ); - - const req = httpTestingController.expectOne(basePath + '/' + service.producersPath + '/producer1/' + service.jobsPath); - expect(req.request.method).toEqual('GET'); - - req.flush(expectedEIJobs); //Return expectedEIJobs - - httpTestingController.verify(); - }); - }); - describe('#getProducer', () => { let expectedProducer: ProducerRegistrationInfo; diff --git a/webapp-frontend/src/app/services/ei/producer.service.ts b/webapp-frontend/src/app/services/ei/producer.service.ts index 2c4571d..1744ff8 100644 --- a/webapp-frontend/src/app/services/ei/producer.service.ts +++ b/webapp-frontend/src/app/services/ei/producer.service.ts @@ -21,7 +21,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; -import { JobInfo, ProducerStatus, ProducerRegistrationInfo } from '@interfaces/producer.types'; +import { ProducerStatus, ProducerRegistrationInfo } from '@interfaces/producer.types'; /** * Services for calling the EI endpoints. @@ -53,11 +53,6 @@ export class ProducerService { return this.httpClient.get(url); } - getJobsForProducer(producerId: string): Observable { - const url = this.buildPath(this.producersPath, producerId, this.jobsPath); - return this.httpClient.get(url); - } - getProducer(producerId: string): Observable { const url = this.buildPath(this.producersPath, producerId); return this.httpClient.get(url); -- 2.16.6