Feature 11009 Ns Config Template as first class citizens in OSM
[osm/NG-UI.git] / src / app / packages / instantiate-ns / InstantiateNsComponent.ts
1 /*
2  Copyright 2020 TATA ELXSI
3
4  Licensed under the Apache License, Version 2.0 (the 'License');
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15
16  Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
17 */
18 /**
19  * @file Instantiate NS Modal Component.
20  */
21 import { Component, ElementRef, Injector, Input, OnInit, ViewChild } from '@angular/core';
22 import { FormBuilder, FormGroup, Validators } from '@angular/forms';
23 import { Router } from '@angular/router';
24 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
25 import { TranslateService } from '@ngx-translate/core';
26 import { NotifierService } from 'angular-notifier';
27 import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA, URLPARAMS } from 'CommonModel';
28 import { DataService } from 'DataService';
29 import { environment } from 'environment';
30 import * as jsyaml from 'js-yaml';
31 import { NSCONFIG } from 'NSCONFIGTEMPLATEMODEL';
32 import { NSData, NSDDetails } from 'NSDModel';
33 import { RestService } from 'RestService';
34 import { Subscription } from 'rxjs';
35 import { SharedService, isNullOrUndefined } from 'SharedService';
36 import { VimAccountDetails } from 'VimAccountModel';
37
38 /**
39  * Creating component
40  * @Component takes InstantiateNsComponent.html as template url
41  */
42 @Component({
43   selector: 'app-instantiate-ns',
44   templateUrl: './InstantiateNsComponent.html',
45   styleUrls: ['./InstantiateNsComponent.scss']
46 })
47 /** Exporting a class @exports InstantiateNsComponent */
48 export class InstantiateNsComponent implements OnInit {
49   /** To inject services @public */
50   public injector: Injector;
51
52   /** Contains all the nsd data collections */
53   public nsdSelect: NSDDetails;
54
55   /** FormGroup instance added to the form @ html @public */
56   public instantiateForm: FormGroup;
57
58   /** Contains all vim account collections */
59   public vimAccountSelect: VimAccountDetails;
60
61   /** Contains all NS Config template details */
62   public nsConfigSelect: NSCONFIG;
63
64   /** Instance for active modal service @public */
65   public activeModal: NgbActiveModal;
66
67   /** Used to subscribe nsdId @public */
68   public nsdID: Subscription;
69
70   /** Variable set for twoway binding @public */
71   public nsdId: string;
72
73   /** Variable set for twoway bindng @public  */
74   public vimAccountId: string;
75
76   /** Form submission Add */
77   public submitted = false;
78
79   /** Check the loading results @public */
80   public isLoadingResults = false;
81
82   /** Give the message for the loading @public */
83   public message = 'PLEASEWAIT';
84
85   /** Contains Selected VIM Details @public */
86   public selectedVIMDetails: VimAccountDetails = null;
87
88   /** Element ref for fileInputConfig @public */
89   @ViewChild('fileInputConfig', { static: true }) public fileInputConfig: ElementRef;
90
91   /** Element ref for fileInputConfigLabel @public */
92   @ViewChild('fileInputConfigLabel', { static: true }) public fileInputConfigLabel: ElementRef;
93
94   /** Element ref for fileInputSSH @public */
95   @ViewChild('fileInputSSH', { static: true }) public fileInputSSH: ElementRef;
96
97   /** Element ref for fileInputSSHLabel @public */
98   @ViewChild('fileInputSSHLabel', { static: true }) public fileInputSSHLabel: ElementRef;
99
100   /** Holds teh instance of AuthService class of type AuthService @private */
101   private router: Router;
102
103   /** FormBuilder instance added to the formBuilder @private */
104   private formBuilder: FormBuilder;
105
106   /** Utilizes rest service for any CRUD operations @private */
107   private restService: RestService;
108
109   /** Utilizes data service for any communication @private */
110   private dataService: DataService;
111
112   /** Notifier service to popup notification @private */
113   private notifierService: NotifierService;
114
115   /** Contains tranlsate instance @private */
116   private translateService: TranslateService;
117
118   /** Contains all methods related to shared @private */
119   private sharedService: SharedService;
120
121   /** Contains the ssh key to be hosted in dom @private */
122   private copySSHKey: string;
123
124   /** Input contains component objects @private */
125   @Input() private params: URLPARAMS;
126
127   constructor(injector: Injector) {
128     this.injector = injector;
129     this.restService = this.injector.get(RestService);
130     this.activeModal = this.injector.get(NgbActiveModal);
131     this.formBuilder = this.injector.get(FormBuilder);
132     this.dataService = this.injector.get(DataService);
133     this.notifierService = this.injector.get(NotifierService);
134     this.router = this.injector.get(Router);
135     this.translateService = this.injector.get(TranslateService);
136     this.sharedService = this.injector.get(SharedService);
137   }
138
139   public ngOnInit(): void {
140     /** Setting up initial value for NSD */
141     this.nsdID = this.dataService.currentMessage.subscribe((event: NSData) => {
142       if (!isNullOrUndefined(event?.identifier) || event?.identifier !== '') {
143         this.nsdId = event.identifier;
144       }
145       this.getDetailsconfigtemplateAccount();
146     });
147     /** On Initializing call the methods */
148     this.instantiateFormAction();
149     this.getDetailsnsd();
150     this.getDetailsvimAccount();
151   }
152
153   /** On modal initializing forms  @public */
154   public instantiateFormAction(): void {
155     this.instantiateForm = this.formBuilder.group({
156       nsName: ['', [Validators.required]],
157       nsDescription: ['', [Validators.required]],
158       nsdId: [null, [Validators.required]],
159       vimAccountId: ['', [Validators.required]],
160       ssh_keys: [null],
161       config: [null],
162       nsConfigTemplateId: [null]
163     });
164   }
165
166   /** Convenience getter for easy access to form fields */
167   get f(): FormGroup['controls'] { return this.instantiateForm.controls; }
168
169   /** Call the nsd details in the selection options @public */
170   public getDetailsnsd(): void {
171     this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL).subscribe((nsPackages: NSDDetails) => {
172       this.nsdSelect = nsPackages;
173     }, (error: ERRORDATA) => {
174       this.restService.handleError(error, 'get');
175     });
176   }
177
178   /** Call the vimAccount details in the selection options @public */
179   public getDetailsvimAccount(): void {
180     this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimAccounts: VimAccountDetails) => {
181       this.vimAccountSelect = vimAccounts;
182     }, (error: ERRORDATA) => {
183       this.restService.handleError(error, 'get');
184     });
185   }
186
187   /** Call the ns config template details in the selection options @public */
188   public getDetailsconfigtemplateAccount(): void {
189     this.restService.getResource(environment.NSCONFIGTEMPLATE_URL + '?nsdId=' + this.nsdId).subscribe((template: NSCONFIG) => {
190       this.nsConfigSelect = template;
191     }, (error: ERRORDATA) => {
192       this.restService.handleError(error, 'get');
193     });
194   }
195
196   /** On modal submit instantiateNsSubmit will called @public */
197   public instantiateNsSubmit(): void {
198     this.submitted = true;
199     this.sharedService.cleanForm(this.instantiateForm);
200     if (this.instantiateForm.invalid) {
201       return;
202     }
203     const modalData: MODALCLOSERESPONSEDATA = {
204       message: 'Done'
205     };
206     if (isNullOrUndefined(this.instantiateForm.value.nsConfigTemplateId)) {
207       delete this.instantiateForm.value.nsConfigTemplateId;
208     }
209     if (isNullOrUndefined(this.instantiateForm.value.ssh_keys) || this.instantiateForm.value.ssh_keys === '') {
210       delete this.instantiateForm.value.ssh_keys;
211     } else {
212       this.copySSHKey = JSON.parse(JSON.stringify(this.instantiateForm.value.ssh_keys));
213       this.instantiateForm.get('ssh_keys').setValue([this.copySSHKey]);
214     }
215     if (isNullOrUndefined(this.instantiateForm.value.config) || this.instantiateForm.value.config === '') {
216       delete this.instantiateForm.value.config;
217     } else {
218       const validJSON: boolean = this.sharedService.checkJson(this.instantiateForm.value.config);
219       if (validJSON) {
220         this.instantiateForm.value.config = JSON.parse(this.instantiateForm.value.config);
221         Object.keys(this.instantiateForm.value.config).forEach((item: string) => {
222           // eslint-disable-next-line security/detect-object-injection
223           this.instantiateForm.value[item] = this.instantiateForm.value.config[item];
224         });
225         delete this.instantiateForm.value.config;
226       } else {
227         const getConfigJson: string = jsyaml.load(this.instantiateForm.value.config, { json: true });
228         Object.keys(getConfigJson).forEach((item: string) => {
229           // eslint-disable-next-line security/detect-object-injection
230           this.instantiateForm.value[item] = getConfigJson[item];
231         });
232         delete this.instantiateForm.value.config;
233       }
234       delete this.instantiateForm.value.nsConfigTemplateId;
235     }
236     const apiURLHeader: APIURLHEADER = {
237       url: environment.NSINSTANCESCONTENT_URL
238     };
239     this.isLoadingResults = true;
240     this.restService.postResource(apiURLHeader, this.instantiateForm.value).subscribe((result: {}) => {
241       this.activeModal.close(modalData);
242       this.notifierService.notify('success', this.instantiateForm.value.nsName +
243         this.translateService.instant('PAGE.NSINSTANCE.CREATEDSUCCESSFULLY'));
244       this.router.navigate(['/instances/ns']).catch((): void => {
245         // Catch Navigation Error
246       });
247     }, (error: ERRORDATA) => {
248       this.isLoadingResults = false;
249       this.restService.handleError(error, 'post');
250       if (!isNullOrUndefined(this.copySSHKey)) {
251         this.instantiateForm.get('ssh_keys').setValue(this.copySSHKey);
252       }
253     });
254   }
255
256   /** ssh file process @private */
257   public sshFile(files: FileList): void {
258     if (files && files.length === 1) {
259       this.sharedService.getFileString(files, 'pub').then((fileContent: string): void => {
260         const getSSHJson: string = jsyaml.load(fileContent, { json: true });
261         this.instantiateForm.get('ssh_keys').setValue(getSSHJson);
262       }).catch((err: string): void => {
263         if (err === 'typeError') {
264           this.notifierService.notify('error', this.translateService.instant('PUBFILETYPEERRROR'));
265         } else {
266           this.notifierService.notify('error', this.translateService.instant('ERROR'));
267         }
268         this.fileInputSSHLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
269         this.fileInputSSH.nativeElement.value = null;
270       });
271     } else if (files && files.length > 1) {
272       this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
273     }
274     this.fileInputSSHLabel.nativeElement.innerText = files[0].name;
275     this.fileInputSSH.nativeElement.value = null;
276   }
277
278   /** Config file process @private */
279   public configFile(files: FileList): void {
280     if (files && files.length === 1) {
281       const fileFormat: string = this.sharedService.fetchFileExtension(files).toLocaleLowerCase();
282       if (fileFormat === 'yaml' || fileFormat === 'yml') {
283         this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => {
284           this.instantiateForm.get('config').setValue(fileContent);
285         }).catch((err: string): void => {
286           if (err === 'typeError') {
287             this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
288           } else {
289             this.notifierService.notify('error', this.translateService.instant('ERROR'));
290           }
291           this.fileInputConfigLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
292           this.fileInputConfig.nativeElement.value = null;
293         });
294       } else if (fileFormat === 'json') {
295         this.sharedService.getFileString(files, 'json').then((fileContent: string): void => {
296           const getConfigJson: string = jsyaml.load(fileContent, { json: true });
297           this.instantiateForm.get('config').setValue(JSON.stringify(getConfigJson));
298         }).catch((err: string): void => {
299           if (err === 'typeError') {
300             this.notifierService.notify('error', this.translateService.instant('JSONFILETYPEERRROR'));
301           } else {
302             this.notifierService.notify('error', this.translateService.instant('ERROR'));
303           }
304           this.fileInputConfigLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
305           this.fileInputConfig.nativeElement.value = null;
306         });
307       }
308     } else if (files && files.length > 1) {
309       this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
310     }
311     this.fileInputConfigLabel.nativeElement.innerText = files[0].name;
312     this.fileInputConfig.nativeElement.value = null;
313   }
314
315   /** Get Selected VIM details @public */
316   public getSelectedVIMDetails(vimDetails: VimAccountDetails): void {
317     if (!isNullOrUndefined(vimDetails.resources)) {
318       this.selectedVIMDetails = vimDetails;
319     }
320   }
321
322   /**
323    * Lifecyle Hooks the trigger before component is deleted
324    */
325   public ngOnDestroy(): void {
326     this.nsdID.unsubscribe();
327   }
328 }