| /* |
| Copyright 2020 TATA ELXSI |
| |
| 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. |
| |
| Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in) |
| */ |
| /** |
| * @file Info Compose Package Model |
| */ |
| import { HttpClient, HttpHeaders } from '@angular/common/http'; |
| import { Component, ElementRef, Injector, Input, OnInit, ViewChild } from '@angular/core'; |
| import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; |
| import { Router } from '@angular/router'; |
| import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; |
| import { TranslateService } from '@ngx-translate/core'; |
| import { NotifierService } from 'angular-notifier'; |
| import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA, URLPARAMS } from 'CommonModel'; |
| import { DataService } from 'DataService'; |
| import { environment } from 'environment'; |
| import * as jsyaml from 'js-yaml'; |
| import { NSConfigData } from 'NSCONFIGTEMPLATEMODEL'; |
| import { NSDDetails } from 'NSDModel'; |
| import * as pako from 'pako'; |
| import { RestService } from 'RestService'; |
| import { SharedService, isNullOrUndefined } from 'SharedService'; |
| |
| /** This is added globally by the tar.js library */ |
| // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| declare const Tar: any; |
| |
| /** |
| * Creating component |
| * @Component takes ComposePackages.html as template url |
| */ |
| @Component({ |
| templateUrl: './ComposePackages.html', |
| styleUrls: ['./ComposePackages.scss'] |
| }) |
| /** Exporting a class @exports ComposePackages */ |
| // eslint-disable-next-line @angular-eslint/component-class-suffix |
| export class ComposePackages implements OnInit { |
| /** Invoke service injectors @public */ |
| public injector: Injector; |
| |
| /** dataService to pass the data from one component to another @public */ |
| public dataService: DataService; |
| |
| /** Varaibles to hold http client @public */ |
| public httpClient: HttpClient; |
| |
| /** Instance for active modal service @public */ |
| public activeModal: NgbActiveModal; |
| |
| /** FormGroup instance added to the form @ html @public */ |
| public packagesForm: FormGroup; |
| |
| /** Form submission Add */ |
| public submitted = false; |
| |
| /** To handle loader status for API call @public */ |
| public isLoadingResults = false; |
| |
| /** Give the message for the loading @public */ |
| public message = 'PLEASEWAIT'; |
| |
| /** contains NSD name @public */ |
| public nsName: {}[] = []; |
| |
| /** contains NSD details @public */ |
| public nsdDetails: {}[]; |
| |
| /** contains NSD details filtered by id @public */ |
| public nsdName: string; |
| |
| /** Contains config details @public */ |
| public config: string; |
| |
| /** contains NSD details filtered by name @public */ |
| public nsId: string; |
| |
| /** Check if template or not @public */ |
| public template = false; |
| |
| /** Data of NS config @public */ |
| public details: NSConfigData; |
| |
| /** Data of NF packages @public */ |
| public nsConfigData: NSConfigData[] = []; |
| |
| /** Element ref for fileInputConfig @public */ |
| @ViewChild('fileInputConfig') fileInputConfig: ElementRef<HTMLInputElement>; |
| |
| /** Element ref for fileInputConfigLabel @public */ |
| @ViewChild('fileInputConfigLabel') fileInputConfigLabel: ElementRef<HTMLLabelElement>; |
| |
| /** FormBuilder instance added to the formBuilder @private */ |
| private formBuilder: FormBuilder; |
| |
| /** Instance of the rest service @private */ |
| private restService: RestService; |
| |
| /** Notifier service to popup notification @private */ |
| private notifierService: NotifierService; |
| |
| /** Controls the header form @private */ |
| private headers: HttpHeaders; |
| |
| /** Input contains component objects @public */ |
| @Input() public params: URLPARAMS; |
| |
| /** Holds the end point @private */ |
| private endPoint: string; |
| |
| /** ModalData instance of modal @private */ |
| private modalData: MODALCLOSERESPONSEDATA; |
| |
| /** Contains all methods related to shared @private */ |
| private sharedService: SharedService; |
| |
| /** Holds teh instance of AuthService class of type AuthService @private */ |
| private router: Router; |
| |
| /** Contains tranlsate instance @private */ |
| private translateService: TranslateService; |
| |
| constructor(injector: Injector) { |
| this.injector = injector; |
| this.dataService = this.injector.get(DataService); |
| this.restService = this.injector.get(RestService); |
| this.activeModal = this.injector.get(NgbActiveModal); |
| this.notifierService = this.injector.get(NotifierService); |
| this.formBuilder = this.injector.get(FormBuilder); |
| this.router = this.injector.get(Router); |
| this.translateService = this.injector.get(TranslateService); |
| this.sharedService = this.injector.get(SharedService); |
| } |
| |
| /** convenience getter for easy access to form fields */ |
| get f(): FormGroup['controls'] { return this.packagesForm.controls; } |
| |
| /** |
| * Lifecyle Hooks the trigger before component is instantiate |
| */ |
| public ngOnInit(): void { |
| this.initializeForm(); |
| if (this.params.page === 'ns-config-template') { |
| this.template = true; |
| this.getNsdPackageDetails(); |
| } else if (this.params.page === 'ns-config-template-edit') { |
| this.template = true; |
| this.getNsdPackageDetails(); |
| this.getFormControl('nsdId').disable(); |
| } else { |
| this.getFormControl('nsdId').disable(); |
| this.getFormControl('config').disable(); |
| } |
| } |
| |
| /** initialize Forms @public */ |
| public initializeForm(): void { |
| this.packagesForm = this.formBuilder.group({ |
| name: ['', [Validators.required]], |
| nsdId: [null, [Validators.required]], |
| config: [null] |
| }); |
| } |
| |
| /** Get NSD Package details @public */ |
| public getNsdPackageDetails(): void { |
| this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL) |
| .subscribe((nsdPackageData: NSDDetails[]): void => { |
| nsdPackageData.forEach((nsData: NSDDetails): void => { |
| const names: {} = { |
| nsName: nsData.name, |
| nsId: nsData._id |
| }; |
| this.nsName.push(names); |
| }); |
| this.nsdDetails = this.nsName; |
| if (this.params.page === 'ns-config-template-edit') { |
| this.getNSConfigDetails(environment.NSCONFIGTEMPLATE_URL + '/' + this.params.id, this.nsdDetails); |
| } |
| }, (error: ERRORDATA): void => { |
| this.restService.handleError(error, 'get'); |
| }); |
| } |
| |
| /** Get the NSD Content List & patch value in edit form @public */ |
| public getNSConfigDetails(URL: string, name: {}[]): void { |
| this.restService.getResource(URL).subscribe((content: NSConfigData): void => { |
| this.nsConfigData.push(content); |
| this.details = this.nsConfigData[0]; |
| const nsId: string = 'nsId'; |
| // eslint-disable-next-line security/detect-object-injection |
| const nsdId: {}[] = name.filter((nsdData: {}[]): boolean => nsdData[nsId] === this.details.nsdId); |
| const nsName: string = 'nsName'; |
| for (const data of nsdId) { |
| // eslint-disable-next-line security/detect-object-injection |
| this.nsdName = data[nsName]; |
| } |
| if (!isNullOrUndefined(this.details.config)) { |
| this.config = jsyaml.dump(this.details.config); |
| } |
| this.packagesForm.patchValue({ name: this.details.name, nsdId: this.nsdName, config: this.config }); |
| this.isLoadingResults = false; |
| }, (error: ERRORDATA): void => { |
| this.restService.handleError(error, 'get'); |
| this.isLoadingResults = false; |
| }); |
| } |
| |
| /** Create packages @public */ |
| public createPackages(): void { |
| this.submitted = true; |
| this.modalData = { |
| message: 'Done' |
| }; |
| this.sharedService.cleanForm(this.packagesForm); |
| if (!this.packagesForm.invalid) { |
| this.isLoadingResults = true; |
| if (this.params.page === 'ns-package' || this.params.page === 'vnf-package') { |
| if (this.params.page === 'ns-package') { |
| this.endPoint = environment.NSDESCRIPTORSCONTENT_URL; |
| } else if (this.params.page === 'vnf-package') { |
| this.endPoint = environment.VNFPACKAGESCONTENT_URL; |
| } |
| const descriptor: string = this.packageYaml(this.params.page); |
| try { |
| // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| const tar: any = new Tar(); |
| const out: Uint8Array = tar.append(this.packagesForm.value.name + '/' + this.packagesForm.value.name + '.yaml', |
| descriptor, { type: '0' }); |
| const gzipContent: Uint8Array = pako.gzip(out); |
| this.createPackageApi(gzipContent.buffer); |
| } catch (e) { |
| this.isLoadingResults = false; |
| this.notifierService.notify('error', this.translateService.instant('ERROR')); |
| } |
| } else { |
| try { |
| this.headers = new HttpHeaders({ |
| Accept: 'application/json', |
| 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0' |
| }); |
| if (this.params.page === 'ns-config-template') { |
| this.endPoint = environment.NSCONFIGTEMPLATE_URL; |
| this.createTemplate(this.endPoint); |
| } else if (this.params.page === 'ns-config-template-edit') { |
| this.endPoint = environment.NSCONFIGTEMPLATE_URL + '/' + this.params.id + '/' + 'template_content'; |
| this.editTemplate(this.endPoint); |
| } |
| } catch (e) { |
| this.isLoadingResults = false; |
| this.notifierService.notify('error', this.translateService.instant('ERROR')); |
| } |
| } |
| } |
| } |
| |
| /** Post config template @public */ |
| public createTemplate(urlHeader: string): void { |
| this.isLoadingResults = true; |
| const apiURLHeader: APIURLHEADER = { |
| url: urlHeader, |
| httpOptions: { headers: this.headers } |
| }; |
| if (isNullOrUndefined(this.packagesForm.value.config) || this.packagesForm.value.config === '') { |
| delete this.packagesForm.value.config; |
| } else { |
| const validJSON: boolean = this.sharedService.checkJson(this.packagesForm.value.config); |
| if (validJSON) { |
| this.packagesForm.value.config = JSON.parse(this.packagesForm.value.config); |
| } else { |
| const getConfigJson: string = jsyaml.load(this.packagesForm.value.config, { json: true }); |
| this.packagesForm.value.config = getConfigJson; |
| } |
| } |
| const nsName: string = 'nsName'; |
| // eslint-disable-next-line security/detect-object-injection |
| const nsdId: {}[] = this.nsdDetails.filter((nsdData: {}[]): boolean => nsdData[nsName] === this.packagesForm.value.nsdId); |
| for (const data of nsdId) { |
| // eslint-disable-next-line @typescript-eslint/dot-notation |
| this.nsId = data['nsId']; |
| } |
| this.packagesForm.value.nsdId = this.nsId; |
| this.restService.postResource(apiURLHeader, (this.packagesForm.value)).subscribe((result: {}): void => { |
| this.activeModal.close(this.modalData); |
| this.isLoadingResults = false; |
| this.notifierService.notify('success', this.translateService.instant('PAGE.NSCONFIGTEMPLATE.TEMPLATECREATEDSUCCESSFULLY')); |
| }, (error: ERRORDATA): void => { |
| this.restService.handleError(error, 'post'); |
| this.isLoadingResults = false; |
| }); |
| } |
| |
| /** Edit config template @public */ |
| public editTemplate(urlHeader: string): void { |
| this.isLoadingResults = true; |
| const apiURLHeader: APIURLHEADER = { |
| url: urlHeader, |
| httpOptions: { headers: this.headers } |
| }; |
| if (isNullOrUndefined(this.packagesForm.value.config) || this.packagesForm.value.config === '') { |
| delete this.packagesForm.value.config; |
| } else { |
| const validJSON: boolean = this.sharedService.checkJson(this.packagesForm.value.config); |
| if (validJSON) { |
| this.packagesForm.value.config = JSON.parse(this.packagesForm.value.config); |
| } else { |
| const getConfigJson: string = jsyaml.load(this.packagesForm.value.config, { json: true }); |
| this.packagesForm.value.config = getConfigJson; |
| } |
| } |
| this.restService.putResource(apiURLHeader, (this.packagesForm.value)).subscribe((result: {}): void => { |
| this.activeModal.close(this.modalData); |
| this.isLoadingResults = false; |
| this.notifierService.notify('success', this.translateService.instant('PAGE.NSCONFIGTEMPLATE.TEMPLATEEDITEDSUCCESSFULLY')); |
| }, (error: ERRORDATA): void => { |
| this.restService.handleError(error, 'post'); |
| this.isLoadingResults = false; |
| }); |
| } |
| /** Create packages @public */ |
| private createPackageApi(packageContent: ArrayBuffer | SharedArrayBuffer): void { |
| this.headers = new HttpHeaders({ |
| 'Content-Type': 'application/gzip', |
| Accept: 'application/json', |
| 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0' |
| }); |
| const apiURLHeader: APIURLHEADER = { |
| url: this.endPoint, |
| httpOptions: { headers: this.headers } |
| }; |
| this.restService.postResource(apiURLHeader, packageContent).subscribe((result: { id: string }): void => { |
| this.isLoadingResults = false; |
| this.activeModal.close(); |
| this.composeNSPackages(result.id); |
| }, (error: ERRORDATA): void => { |
| this.isLoadingResults = false; |
| this.restService.handleError(error, 'post'); |
| }); |
| } |
| /** Config file process @private */ |
| public configFile(files: FileList): void { |
| if (files && files.length === 1) { |
| const fileFormat: string = this.sharedService.fetchFileExtension(files).toLocaleLowerCase(); |
| if (fileFormat === 'yaml' || fileFormat === 'yml') { |
| this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => { |
| this.packagesForm.get('config').setValue(fileContent); |
| }).catch((err: string): void => { |
| if (err === 'typeError') { |
| this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR')); |
| } else { |
| this.notifierService.notify('error', this.translateService.instant('ERROR')); |
| } |
| this.fileInputConfigLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE'); |
| this.fileInputConfig.nativeElement.value = null; |
| }); |
| } else if (fileFormat === 'json') { |
| this.sharedService.getFileString(files, 'json').then((fileContent: string): void => { |
| const getConfigJson: string = jsyaml.load(fileContent, { json: true }); |
| this.packagesForm.get('config').setValue(JSON.stringify(getConfigJson)); |
| }).catch((err: string): void => { |
| if (err === 'typeError') { |
| this.notifierService.notify('error', this.translateService.instant('JSONFILETYPEERRROR')); |
| } else { |
| this.notifierService.notify('error', this.translateService.instant('ERROR')); |
| } |
| this.fileInputConfigLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE'); |
| this.fileInputConfig.nativeElement.value = null; |
| }); |
| } |
| } else if (files && files.length > 1) { |
| this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION')); |
| } |
| this.fileInputConfigLabel.nativeElement.innerText = files[0].name; |
| this.fileInputConfig.nativeElement.value = null; |
| } |
| /** Compose NS Packages @private */ |
| private composeNSPackages(id: string): void { |
| let packageUrl: string; |
| if (this.params.page === 'ns-package') { |
| packageUrl = '/packages/ns/compose/'; |
| this.notifierService.notify('success', this.packagesForm.value.name + ' ' + |
| this.translateService.instant('PAGE.NSPACKAGE.CREATEDSUCCESSFULLY')); |
| } else if (this.params.page === 'vnf-package') { |
| packageUrl = '/packages/vnf/compose/'; |
| this.notifierService.notify('success', this.packagesForm.value.name + ' ' + |
| this.translateService.instant('PAGE.VNFPACKAGE.CREATEDSUCCESSFULLY')); |
| } |
| this.router.navigate([packageUrl, id]).catch((): void => { |
| // Catch Navigation Error |
| }); |
| } |
| /** Deafult template for NS and VNF Packages @private */ |
| private packageYaml(descriptorType: string): string { |
| let packageYaml: {} = {}; |
| const composerName: string = 'NGUI Composer'; |
| const composerDefaultVersion: string = '1.0'; |
| if (descriptorType === 'ns-package') { |
| packageYaml = { |
| nsd: { |
| nsd: [ |
| { |
| id: this.packagesForm.value.name, |
| name: this.packagesForm.value.name, |
| version: composerDefaultVersion, |
| description: this.packagesForm.value.name + ' descriptor', |
| designer: composerName, |
| df: [ |
| { |
| id: 'default-df', |
| 'vnf-profile': [] |
| } |
| ] |
| } |
| ] |
| } |
| }; |
| } else { |
| packageYaml = { |
| vnfd: { |
| id: this.packagesForm.value.name, |
| 'product-name': this.packagesForm.value.name, |
| version: composerDefaultVersion, |
| description: this.packagesForm.value.name + ' descriptor', |
| provider: composerName, |
| df: [ |
| { |
| id: 'default-df', |
| 'instantiation-level': [], |
| 'vdu-profile': [] |
| } |
| ], |
| 'ext-cpd': [], |
| vdu: [], |
| 'sw-image-desc': [], |
| 'virtual-storage-desc': [] |
| } |
| }; |
| } |
| return jsyaml.dump(packageYaml, { sortKeys: true }); |
| } |
| |
| /** Used to get the AbstractControl of controlName passed @private */ |
| private getFormControl(controlName: string): AbstractControl { |
| // eslint-disable-next-line security/detect-object-injection |
| return this.packagesForm.controls[controlName]; |
| } |
| } |