From: Lathish Date: Tue, 26 Jan 2021 14:23:10 +0000 (+0000) Subject: Add A1 Policy Instance logic from backend X-Git-Tag: 2.2.0~109 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F09%2F5509%2F3;p=portal%2Fnonrtric-controlpanel.git Add A1 Policy Instance logic from backend Issue-ID: NONRTRIC-412 Change-Id: I73c9e15543a530a4d29f7564b1c9e7a5a78cf826 Signed-off-by: Lathish --- diff --git a/webapp-frontend/.gitignore b/webapp-frontend/.gitignore index 588ac10..519a044 100644 --- a/webapp-frontend/.gitignore +++ b/webapp-frontend/.gitignore @@ -39,3 +39,4 @@ /nbdist/ /.nb-gradle/ /build/ +/bin/ diff --git a/webapp-frontend/nginx.conf b/webapp-frontend/nginx.conf index 4700d85..8ae7bd8 100644 --- a/webapp-frontend/nginx.conf +++ b/webapp-frontend/nginx.conf @@ -4,8 +4,7 @@ http { include /etc/nginx/mime.types; upstream backend { - # to be replaced with hostname:port of nonrtric-gateway once it gets ready - server nonrtricgateway:8080; + server nonrtricgateway:9090; } server { @@ -13,8 +12,11 @@ http { server_name localhost; root /usr/share/nginx/html; index index.html; - location /api/ { + location /v2/ { proxy_pass http://backend; } + location / { + try_files $uri $uri/ /index.html; + } } } \ No newline at end of file diff --git a/webapp-frontend/src/app/interceptor.mock.ts b/webapp-frontend/src/app/interceptor.mock.ts index e444d91..25439ae 100644 --- a/webapp-frontend/src/app/interceptor.mock.ts +++ b/webapp-frontend/src/app/interceptor.mock.ts @@ -22,10 +22,13 @@ import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } fr import { Injectable, Injector } from '@angular/core'; import { Observable, of } from 'rxjs'; import * as policyinstances1 from './mock/policy-instance-1.json'; -import * as policyinstancesNoType from './mock/policy-instance-notype.json'; +import * as policies from './mock/policies.json'; +import * as policyinstances2 from './mock/policy-instance-2.json'; +import * as policyinstances1Status from './mock/policy-instance-1-status.json'; +import * as policyinstances2Status from './mock/policy-instance-2-status.json'; import * as eijobs from './mock/ei-jobs.json'; import * as eiproducers from './mock/ei-producers.json'; -import * as nopolicyinstances from './mock/nopolicyinstances.json'; +import * as policyinstanceNoType from './mock/policy-instance-notype.json'; import * as policytypesList from './mock/policy-types.json'; import * as policytypes1 from './mock/policy-type1.json'; import * as policyinstanceedit from './mock/policy-instance-edit.json'; @@ -45,27 +48,43 @@ const urls = [ json: policytypes1 }, { - url: 'v2/policies?type=1', + url: 'v2/policies?policytype_id=', + json: policies + }, + { + url: 'v2/policies?policytype_id=1', + json: policies + }, + { + url: 'v2/policies/2000', json: policyinstances1 }, { - url: 'v2/policies?type=', - json: policyinstancesNoType + url: 'v2/policies/2100', + json: policyinstances2 }, { - url: 'v2/policies?type=2', - json: nopolicyinstances + url: 'v2/policies/2000/status', + json: policyinstances1Status }, { - url: 'v2/policies/2000?type=1', + url: 'v2/policies/2100/status', + json: policyinstances2Status + }, + { + url: 'v2/policies/2000?type=', json: policyinstanceedit }, { - url: 'v2/policies/3000?type=1', + url: 'v2/policies/2100?type=', + json: policyinstanceedit + }, + { + url: 'v2/policies/2000?type=1', json: policyinstanceedit }, { - url: 'v2/policies/2001?type=', + url: 'v2/policies/2100?type=1', json: policyinstanceedit }, { diff --git a/webapp-frontend/src/app/interfaces/policy.types.ts b/webapp-frontend/src/app/interfaces/policy.types.ts index 8bc5eb1..9688a23 100644 --- a/webapp-frontend/src/app/interfaces/policy.types.ts +++ b/webapp-frontend/src/app/interfaces/policy.types.ts @@ -21,6 +21,7 @@ // Models of data used by the Policy Control export interface PolicyTypeSchema { + id: string; name: string; schemaObject: any; } @@ -33,13 +34,20 @@ export interface PolicyTypes { policytype_ids: any[]; } +export interface PolicyInstances { + policy_ids: any[]; +} + export interface PolicyInstance { - id: string; - json: string; - ric: string; - service: string; + policy_id: string; + policy_data: string; + ric_id: string; + service_id: string; lastModified: string; } +export interface PolicyStatus { + last_modified: string; +} export interface PolicyInstanceAck { status: string; diff --git a/webapp-frontend/src/app/mock/policies.json b/webapp-frontend/src/app/mock/policies.json new file mode 100644 index 0000000..c392b76 --- /dev/null +++ b/webapp-frontend/src/app/mock/policies.json @@ -0,0 +1,5 @@ +{ + "policy_ids": [ + "2100" + ] +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/policy-instance-1-status.json b/webapp-frontend/src/app/mock/policy-instance-1-status.json new file mode 100644 index 0000000..4340716 --- /dev/null +++ b/webapp-frontend/src/app/mock/policy-instance-1-status.json @@ -0,0 +1,8 @@ +{ + "last_modified": "2021-01-26T13:15:11.827435Z", + "status": { + "instance_status": "NOT IN EFFECT", + "has_been_deleted": "false", + "created_at": "01/26/2021, 13:15:11" + } +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/policy-instance-1.json b/webapp-frontend/src/app/mock/policy-instance-1.json index 3dc9fa7..df20f43 100644 --- a/webapp-frontend/src/app/mock/policy-instance-1.json +++ b/webapp-frontend/src/app/mock/policy-instance-1.json @@ -1,34 +1,17 @@ -[ - { - "id": "2000", - "type": "1", - "ric": "ric1", - "json": { - "scope": { - "ueId": "ue3100", - "qosId": "qos3100" - }, - "qosObjectives": { - "priorityLevel": 3100 - } - }, - "service": "service1", - "lastModified": "2020-12-08T21:12:43.719084Z" +{ + "policy_id": "2000", + "policytype_id": "1", + "ric_id": "ric1", + "policy_data": { + "scope": { + "ueId": "ue3100", + "qosId": "qos3100" }, - { - "id": "3000", - "type": "1", - "ric": "ric2", - "json": { - "scope": { - "ueId": "ue3300", - "qosId": "qos3300" - }, - "qosObjectives": { - "priorityLevel": 3300 - } - }, - "service": "service1", - "lastModified": "2020-12-08T21:12:43.719084Z" + "qosObjectives": { + "priorityLevel": 3100 } - ] \ No newline at end of file + }, + "service_id": "service1", + "transient": false, + "status_notification_uri": "" +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/policy-instance-2-status.json b/webapp-frontend/src/app/mock/policy-instance-2-status.json new file mode 100644 index 0000000..e213694 --- /dev/null +++ b/webapp-frontend/src/app/mock/policy-instance-2-status.json @@ -0,0 +1,6 @@ +{ + "last_modified": "2021-01-26T13:15:11.895297Z", + "status": { + "enforceStatus": "UNDEFINED" + } +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/policy-instance-2.json b/webapp-frontend/src/app/mock/policy-instance-2.json new file mode 100644 index 0000000..69ab3a4 --- /dev/null +++ b/webapp-frontend/src/app/mock/policy-instance-2.json @@ -0,0 +1,17 @@ +{ + "policy_id": "2100", + "policytype_id": "", + "ric_id": "ric2", + "policy_data": { + "scope": { + "ueId": "ue3100", + "qosId": "qos3100" + }, + "qosObjectives": { + "priorityLevel": 3100 + } + }, + "service_id": "service1", + "transient": false, + "status_notification_uri": "" +} \ No newline at end of file diff --git a/webapp-frontend/src/app/mock/policy-instance-notype.json b/webapp-frontend/src/app/mock/policy-instance-notype.json index 25b75ee..7c91060 100644 --- a/webapp-frontend/src/app/mock/policy-instance-notype.json +++ b/webapp-frontend/src/app/mock/policy-instance-notype.json @@ -1,7 +1,7 @@ [ { "id": "2001", - "type": "2", + "type": "", "ric": "ric1", "json": { "scope": { diff --git a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts index 781efca..319efaa 100644 --- a/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts +++ b/webapp-frontend/src/app/policy-control/policy-instance-dialog.component.ts @@ -225,10 +225,10 @@ export class PolicyInstanceDialogComponent implements OnInit, AfterViewInit { export function getPolicyDialogProperties(policyTypeSchema: PolicyTypeSchema, instance: PolicyInstance, darkMode: boolean): MatDialogConfig { const createSchema = policyTypeSchema.schemaObject; - const instanceId = instance ? instance.id : null; - const instanceJson = instance ? instance.json : null; + const instanceId = instance ? instance.policy_id : null; + const instanceJson = instance ? instance.policy_data : null; const name = policyTypeSchema.name; - const ric = instance ? instance.ric : null; + const ric = instance ? instance.ric_id : null; return { maxWidth: '1200px', maxHeight: '900px', diff --git a/webapp-frontend/src/app/policy-control/policy-instance.component.html b/webapp-frontend/src/app/policy-control/policy-instance.component.html index 1e80d83..eca57ab 100644 --- a/webapp-frontend/src/app/policy-control/policy-instance.component.html +++ b/webapp-frontend/src/app/policy-control/policy-instance.component.html @@ -24,7 +24,7 @@ Instance - {{element.id}} + {{element.policy_id}} @@ -33,7 +33,7 @@ matTooltip="Element where the policy instance resides, e.g. a gNodeB or Near-RT RIC"> Target - {{element.ric}} + {{element.ric_id}} @@ -42,7 +42,7 @@ matTooltip="The service that created the policy instance, and is responsible for its lifecycle"> Owner - {{element.service}} + {{element.service_id}} diff --git a/webapp-frontend/src/app/policy-control/policy-instance.component.ts b/webapp-frontend/src/app/policy-control/policy-instance.component.ts index f77bd83..bc8aa32 100644 --- a/webapp-frontend/src/app/policy-control/policy-instance.component.ts +++ b/webapp-frontend/src/app/policy-control/policy-instance.component.ts @@ -59,7 +59,7 @@ export class PolicyInstanceComponent implements OnInit, AfterViewInit { } ngOnInit() { - this.instanceDataSource = new PolicyInstanceDataSource(this.policySvc, this.sort, this.notificationService, this.policyTypeSchema); + this.instanceDataSource = new PolicyInstanceDataSource(this.policySvc, this.sort, this.notificationService,this.policyTypeSchema); this.expanded.subscribe((isExpanded: boolean) => this.onExpand(isExpanded)); this.ui.darkModeState.subscribe((isDark) => { this.darkMode = isDark; @@ -72,7 +72,7 @@ export class PolicyInstanceComponent implements OnInit, AfterViewInit { private onExpand(isExpanded: boolean) { if (isExpanded) { - this.instanceDataSource.loadTable(); + this.instanceDataSource.getPolicyInstances(); } } @@ -81,15 +81,15 @@ export class PolicyInstanceComponent implements OnInit, AfterViewInit { } modifyInstance(instance: PolicyInstance): void { - this.policySvc.getPolicy(this.policyTypeSchema.name, instance.id).subscribe( + this.policySvc.getPolicy(this.policyTypeSchema.name, instance.policy_id).subscribe( (refreshedJson: any) => { - instance.json = JSON.stringify(refreshedJson); + instance.policy_data = JSON.stringify(refreshedJson); if (this.isSchemaEmpty()) { this.dialog.open( NoTypePolicyInstanceDialogComponent, getPolicyDialogProperties(this.policyTypeSchema, instance, this.darkMode)).afterClosed().subscribe( (_: any) => { - this.instanceDataSource.loadTable(); + this.instanceDataSource.getPolicyInstances(); } ); } else { @@ -97,7 +97,7 @@ export class PolicyInstanceComponent implements OnInit, AfterViewInit { PolicyInstanceDialogComponent, getPolicyDialogProperties(this.policyTypeSchema, instance, this.darkMode)).afterClosed().subscribe( (_: any) => { - this.instanceDataSource.loadTable(); + this.instanceDataSource.getPolicyInstances(); } ); @@ -126,13 +126,13 @@ export class PolicyInstanceComponent implements OnInit, AfterViewInit { .afterClosed().subscribe( (res: any) => { if (res) { - this.policySvc.deletePolicy(this.policyTypeSchema.name, instance.id) + this.policySvc.deletePolicy(this.policyTypeSchema.name, instance.policy_id) .subscribe( (response: HttpResponse) => { switch (response.status) { case 200: this.notificationService.success('Delete succeeded!'); - this.instanceDataSource.loadTable(); + this.instanceDataSource.getPolicyInstances(); break; default: this.notificationService.warn('Delete failed ' + response.status + ' ' + response.body); diff --git a/webapp-frontend/src/app/policy-control/policy-instance.datasource.ts b/webapp-frontend/src/app/policy-control/policy-instance.datasource.ts index 4bf2aad..5002522 100644 --- a/webapp-frontend/src/app/policy-control/policy-instance.datasource.ts +++ b/webapp-frontend/src/app/policy-control/policy-instance.datasource.ts @@ -32,6 +32,8 @@ import { NotificationService } from '../services/ui/notification.service'; export class PolicyInstanceDataSource extends DataSource { + policyInstances: PolicyInstance[] = []; + private policyInstanceSubject = new BehaviorSubject([]); private loadingSubject = new BehaviorSubject(false); @@ -48,20 +50,22 @@ export class PolicyInstanceDataSource extends DataSource { super(); } - loadTable() { - this.loadingSubject.next(true); - this.policySvc.getPolicyInstances(this.policyTypeSchema.name) - .pipe( - catchError((her: HttpErrorResponse) => { - this.notificationService.error('Failed to get policy instances: ' + her.error); - return of([]); - }), - finalize(() => this.loadingSubject.next(false)) - ) - .subscribe((instances: PolicyInstance[]) => { - this.rowCount = instances.length; - this.policyInstanceSubject.next(instances); - }); + public getPolicyInstances() { + this.policyInstances = [] as PolicyInstance[]; + this.policySvc.getPolicyInstancesByType(this.policyTypeSchema.id).subscribe(policies => { + if (policies.policy_ids.length != 0) { + policies.policy_ids.forEach(policyId => { + var policyInstance = {} as PolicyInstance + this.policySvc.getPolicyInstance(policyId).subscribe(policyInstance => { + this.policySvc.getPolicyStatus(policyId).subscribe(policyStatus => { + policyInstance.lastModified = policyStatus.last_modified; + }) + this.policyInstances.push(policyInstance); + }) + this.policyInstanceSubject.next(this.policyInstances); + }) + } + }) } connect(): Observable { @@ -87,9 +91,9 @@ export class PolicyInstanceDataSource extends DataSource { return data.sort((a, b) => { const isAsc = this.sort.direction === 'asc'; switch (this.sort.active) { - case 'instanceId': return compare(a.id, b.id, isAsc); - case 'ric': return compare(a.ric, b.ric, isAsc); - case 'service': return compare(a.service, b.service, isAsc); + case 'instanceId': return compare(a.policy_id, b.policy_id, isAsc); + case 'ric': return compare(a.ric_id, b.ric_id, isAsc); + case 'service': return compare(a.service_id, b.service_id, isAsc); case 'lastModified': return compare(a.lastModified, b.lastModified, isAsc); default: return 0; } diff --git a/webapp-frontend/src/app/policy-control/policy-type.datasource.ts b/webapp-frontend/src/app/policy-control/policy-type.datasource.ts index db8f01f..2fed8f3 100644 --- a/webapp-frontend/src/app/policy-control/policy-type.datasource.ts +++ b/webapp-frontend/src/app/policy-control/policy-type.datasource.ts @@ -47,17 +47,19 @@ export class PolicyTypeDataSource extends DataSource { public getPolicyTypes() { this.policyTypes = [] as PolicyTypeSchema[]; - this.policySvc.getPolicyTypes().subscribe(data => { - if (data.policytype_ids.length != 0) { - data.policytype_ids.forEach(policyId => { + this.policySvc.getPolicyTypes().subscribe(policyType => { + if (policyType.policytype_ids.length != 0) { + policyType.policytype_ids.forEach(policyTypeId => { var policyTypeSchema = {} as PolicyTypeSchema - if (policyId === "") { + if (policyTypeId === "") { + policyTypeSchema.id = ''; policyTypeSchema.name = ''; policyTypeSchema.schemaObject = '{}'; this.policyTypes.push(policyTypeSchema); } else { - this.policySvc.getPolicyType(policyId).subscribe(policyType => { + this.policySvc.getPolicyType(policyTypeId).subscribe(policyType => { + policyTypeSchema.id = policyTypeId; policyTypeSchema.schemaObject = policyType.policy_schema; policyTypeSchema.name = policyType.policy_schema.title; this.policyTypes.push(policyTypeSchema); diff --git a/webapp-frontend/src/app/services/policy/policy.service.spec.ts b/webapp-frontend/src/app/services/policy/policy.service.spec.ts index ee20509..3e366da 100644 --- a/webapp-frontend/src/app/services/policy/policy.service.spec.ts +++ b/webapp-frontend/src/app/services/policy/policy.service.spec.ts @@ -21,7 +21,7 @@ import { TestBed } from '@angular/core/testing'; import { PolicyService } from './policy.service'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing' -import { PolicyInstance, PolicyTypes } from '../../interfaces/policy.types'; +import { PolicyInstance, PolicyInstances, PolicyTypes } from '../../interfaces/policy.types'; describe('PolicyService', () => { let apiVersion2 = 'v2' @@ -59,7 +59,7 @@ describe('PolicyService', () => { policytypes => expect(policytypes).toEqual(expectedPolicytypes, 'should return expected PolicyTypes'), fail ); - + const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyTypesPath); expect(req.request.method).toEqual('GET'); @@ -81,36 +81,71 @@ describe('PolicyService', () => { req.flush(emptyPolicyType); //Return empty data }); }); - describe('#getPolicyInstance', () => { - let expectedPolicyInstances: PolicyInstance[]; - let policyTypeId: string; + describe('#getPolicyInstances', () => { + let expectedPolicyInstances: PolicyInstances; + let emptyPolicyInstances: PolicyInstances; + let policyTypeId = '1'; beforeEach(() => { policyService = TestBed.get(PolicyService); httpTestingController = TestBed.get(HttpTestingController); - expectedPolicyInstances = [ - { id: '2000', json: '{"scope": {"ueId": "ue3100","qosId": "qos3100"},"qosObjectives": {"priorityLevel": 3100}}', service: 'service1', lastModified: '2020-12-08T21:12:43.719084Z' } - ] as PolicyInstance[]; - policyTypeId = "1"; + expectedPolicyInstances = { + "policy_ids": [ + "2100", + "2000" + ] + } as PolicyInstances; }); //Policy Instances Test Case 1: it('should return all policy instances', () => { - policyService.getPolicyInstances(policyTypeId).subscribe( + policyService.getPolicyInstancesByType(policyTypeId).subscribe( policyinstances => expect(policyinstances).toEqual(expectedPolicyInstances, 'should return expected Policy Instances'), fail ); - const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyPath + '?type=' + policyTypeId); + const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyPath + '?' + 'policytype_id=' + policyTypeId); expect(req.request.method).toEqual('GET'); req.flush(expectedPolicyInstances); }); //Policy Instances Test Case 2: + emptyPolicyInstances = { + "policy_ids": [ + ] + } as PolicyInstances; it('should return no policy instances', () => { - policyService.getPolicyInstances(policyTypeId).subscribe( - policyinstances => expect(policyinstances.length).toEqual(0, 'should return empty array of Policy Instances'), + policyService.getPolicyInstancesByType(policyTypeId).subscribe( + policyinstances => expect(policyinstances.policy_ids.length).toEqual(0, 'should return empty array of Policy Instances'), + fail + ); + const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyPath + '?' + 'policytype_id=' + policyTypeId); + req.flush(emptyPolicyInstances); //Return empty data + }); + }); + + describe('#getPolicyInstance', () => { + let expectedPolicyInstance: PolicyInstance; + let emptyPolicyInstances: PolicyInstances; + let policyId = "2000"; + beforeEach(() => { + policyService = TestBed.get(PolicyService); + httpTestingController = TestBed.get(HttpTestingController); + expectedPolicyInstance = { + "policy_id": "2000", + "policytype_id": "1", + "ric_id": "ric1", + "policy_data": "", + "service_id": "service1", + "lastModified": "" + } as PolicyInstance; + }); + //Policy Instances Test Case 1: + it('should return one policy instance', () => { + policyService.getPolicyInstance(policyId).subscribe( + policyinstance => expect(policyinstance).toEqual(expectedPolicyInstance, 'should return expected Policy Instances'), fail ); - const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyPath + '?type=' + policyTypeId); - req.flush([]); //Return empty data + const req = httpTestingController.expectOne(basePath + apiVersion2 + '/' + policyService.policyPath + '/' + policyId); + expect(req.request.method).toEqual('GET'); + req.flush(expectedPolicyInstance); }); }); }); diff --git a/webapp-frontend/src/app/services/policy/policy.service.ts b/webapp-frontend/src/app/services/policy/policy.service.ts index c903b2c..482fe87 100644 --- a/webapp-frontend/src/app/services/policy/policy.service.ts +++ b/webapp-frontend/src/app/services/policy/policy.service.ts @@ -22,7 +22,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { PolicyInstance, PolicyInstanceAck, PolicyType, PolicyTypes } from '../../interfaces/policy.types'; +import { PolicyInstance, PolicyInstanceAck, PolicyInstances, PolicyStatus, PolicyType, PolicyTypes } from '../../interfaces/policy.types'; import { ControlpanelSuccessTransport } from '../../interfaces/controlpanel.types'; /** @@ -60,9 +60,19 @@ export class PolicyService { return this.httpClient.get(url); } - getPolicyInstances(policyTypeId: string): Observable { - const url = this.buildPath(this.policyPath) + '?type=' + policyTypeId; - return this.httpClient.get(url); + getPolicyInstancesByType(policyTypeId: string): Observable { + const url = this.buildPath(this.policyPath + '?' + 'policytype_id=' + policyTypeId); + return this.httpClient.get(url); + } + + getPolicyInstance(policyId: string): Observable { + const url = this.buildPath(this.policyPath) + '/' + policyId; + return this.httpClient.get(url); + } + + getPolicyStatus(policyId: string): Observable { + const url = this.buildPath(this.policyPath) + '/' + policyId + '/status'; + return this.httpClient.get(url); } /**