Feature 10904: Make all deployment methods optional for K8s cluster
[osm/NG-UI.git] / src / app / k8s / k8s-add-cluster / K8sAddClusterComponent.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 K8sAddClusterComponent.ts.
20  */
21 import { HttpHeaders } from '@angular/common/http';
22 import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
23 import { FormBuilder, FormGroup, Validators } from '@angular/forms';
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, TYPESECTION } from 'CommonModel';
28 import { environment } from 'environment';
29 import * as jsyaml from 'js-yaml';
30 import { RestService } from 'RestService';
31 import { SharedService } from 'SharedService';
32 import { isNullOrUndefined } from 'util';
33 import { VimAccountDetails } from 'VimAccountModel';
34 /**
35  * Creating Component
36  * @Component takes K8sAddClusterComponent.html as template url
37  */
38 @Component({
39   selector: 'app-k8s-add-cluster',
40   templateUrl: './K8sAddClusterComponent.html',
41   styleUrls: ['./K8sAddClusterComponent.scss']
42 })
43 /** Exporting a class @exports K8sAddClusterComponent */
44 export class K8sAddClusterComponent implements OnInit {
45   /** To inject services @public */
46   public injector: Injector;
47
48   /** FormGroup instance added to the form @ html @public */
49   public k8sclusterForm: FormGroup;
50
51   /** Contains all vim account collections */
52   public vimAccountSelect: VimAccountDetails;
53
54   /** Contains all deployment methods */
55   public deploymentMethodsSelect: TYPESECTION[] = [];
56
57   /** Submited deployments methods format */
58   public deploymentMethodsSubmit: Map<string, boolean>;
59
60   /** Contains all deployment methods selected */
61   public selectedDeploymentMethods: string[] = ['helm-chart-v2', 'helm-chart-v3', 'juju-bundle'];
62
63   /** Instance for active modal service @public */
64   public activeModal: NgbActiveModal;
65
66   /** Variable set for twoway bindng @public  */
67   public vimAccountId: string;
68
69   /** Form submission Add */
70   public submitted: boolean = false;
71
72   /** Check the loading results @public */
73   public isLoadingResults: boolean = false;
74
75   /** Give the message for the loading @public */
76   public message: string = 'PLEASEWAIT';
77
78   /** Element ref for fileInputNets @public */
79   @ViewChild('fileInputNets', { static: true }) public fileInputNets: ElementRef;
80
81   /** Element ref for fileInputNetsLabel @public */
82   @ViewChild('fileInputNetsLabel', { static: true }) public fileInputNetsLabel: ElementRef;
83
84   /** Element ref for fileInputCredentials @public */
85   @ViewChild('fileInputCredentials', { static: true }) public fileInputCredentials: ElementRef;
86
87   /** Element ref for fileInputCredentialsLabel @public */
88   @ViewChild('fileInputCredentialsLabel', { static: true }) public fileInputCredentialsLabel: ElementRef;
89
90   /** FormBuilder instance added to the formBuilder @private */
91   private formBuilder: FormBuilder;
92
93   /** Utilizes rest service for any CRUD operations @private */
94   private restService: RestService;
95
96   /** Notifier service to popup notification @private */
97   private notifierService: NotifierService;
98
99   /** Contains tranlsate instance @private */
100   private translateService: TranslateService;
101
102   /** Controls the header form @private */
103   private headers: HttpHeaders;
104
105   /** Contains all methods related to shared @private */
106   private sharedService: SharedService;
107
108   constructor(injector: Injector) {
109     this.injector = injector;
110     this.restService = this.injector.get(RestService);
111     this.activeModal = this.injector.get(NgbActiveModal);
112     this.formBuilder = this.injector.get(FormBuilder);
113     this.notifierService = this.injector.get(NotifierService);
114     this.translateService = this.injector.get(TranslateService);
115     this.sharedService = this.injector.get(SharedService);
116     this.deploymentMethodsSelect = [
117       {
118         title: 'Helm v2',
119         value: 'helm-chart-v2'
120       },
121       {
122         title: 'Helm v3',
123         value: 'helm-chart-v3'
124       },
125       {
126         title: 'Juju bundle',
127         value: 'juju-bundle'
128       }
129     ];
130   }
131
132   public ngOnInit(): void {
133     /** On Initializing call the methods */
134     this.k8sclusterFormAction();
135     this.getDetailsvimAccount();
136     this.headers = new HttpHeaders({
137       Accept: 'application/json',
138       'Content-Type': 'application/json',
139       'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
140     });
141   }
142
143   /** On modal initializing forms  @public */
144   public k8sclusterFormAction(): void {
145     this.k8sclusterForm = this.formBuilder.group({
146       name: ['', [Validators.required]],
147       k8s_version: ['', [Validators.required]],
148       vim_account: [null, [Validators.required]],
149       description: ['', [Validators.required]],
150       nets: ['', [Validators.required]],
151       deployment_methods: ['', [Validators.required]],
152       credentials: ['', [Validators.required]]
153     });
154   }
155
156   /** convenience getter for easy access to form fields */
157   get f(): FormGroup['controls'] { return this.k8sclusterForm.controls; }
158
159   /** Call the vimAccount details in the selection options @public */
160   public getDetailsvimAccount(): void {
161     this.isLoadingResults = true;
162     this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimAccounts: VimAccountDetails) => {
163       this.vimAccountSelect = vimAccounts;
164       this.isLoadingResults = false;
165     }, (error: ERRORDATA) => {
166       this.restService.handleError(error, 'get');
167       this.isLoadingResults = false;
168     });
169   }
170
171   /** On modal submit k8sAddClusterSubmit will called @public */
172   public k8sAddClusterSubmit(): void {
173     this.submitted = true;
174     this.sharedService.cleanForm(this.k8sclusterForm);
175     if (this.k8sclusterForm.invalid) {
176       return;
177     }
178     const modalData: MODALCLOSERESPONSEDATA = {
179       message: 'Done'
180     };
181     const apiURLHeader: APIURLHEADER = {
182       url: environment.K8SCLUSTER_URL,
183       httpOptions: { headers: this.headers }
184     };
185     const validJSONCredentails: boolean = this.sharedService.checkJson(this.k8sclusterForm.value.credentials);
186     if (validJSONCredentails) {
187       this.k8sclusterForm.value.credentials = jsyaml.load(this.k8sclusterForm.value.credentials.toString(), { json: true });
188     } else {
189       this.notifierService.notify('error', this.translateService.instant('INVALIDCONFIG'));
190       return;
191     }
192     const validJSONNets: boolean = this.sharedService.checkJson(this.k8sclusterForm.value.nets);
193     if (validJSONNets) {
194       this.k8sclusterForm.value.nets = jsyaml.load(this.k8sclusterForm.value.nets.toString(), { json: true });
195     } else {
196       this.notifierService.notify('error', this.translateService.instant('INVALIDCONFIG'));
197       return;
198     }
199
200     this.deploymentMethodsSubmit = new Map<string, boolean>();
201     /// Set deployment method Map
202     for (const methods of this.deploymentMethodsSelect) {
203       this.deploymentMethodsSubmit.set(methods.value, false);
204     }
205
206     this.k8sclusterForm.value.deployment_methods.forEach((dm: string): void => {
207       this.deploymentMethodsSubmit.set(dm, true);
208     });
209     // Transform Map to json object
210     const jsonDMObject: {} = {};
211     this.deploymentMethodsSubmit.forEach((value: boolean, key: string): void => {
212       jsonDMObject[key] = value;
213     });
214
215     // Transform values to json
216     this.k8sclusterForm.value.deployment_methods = jsonDMObject;
217
218     this.isLoadingResults = true;
219     this.restService.postResource(apiURLHeader, this.k8sclusterForm.value).subscribe((result: {}) => {
220       this.activeModal.close(modalData);
221       this.isLoadingResults = false;
222       this.notifierService.notify('success', this.k8sclusterForm.value.name +
223         this.translateService.instant('PAGE.K8S.CREATEDSUCCESSFULLY'));
224     }, (error: ERRORDATA) => {
225       this.restService.handleError(error, 'post');
226       this.isLoadingResults = false;
227     });
228   }
229
230   /** Nets file process @private */
231   public netsFile(files: FileList): void {
232     if (files && files.length === 1) {
233       this.sharedService.getFileString(files, 'json').then((fileContent: string): void => {
234         const getNetsJson: string = jsyaml.load(fileContent, { json: true });
235         // tslint:disable-next-line: no-backbone-get-set-outside-model
236         this.k8sclusterForm.get('nets').setValue(JSON.stringify(getNetsJson));
237       }).catch((err: string): void => {
238         if (err === 'typeError') {
239           this.notifierService.notify('error', this.translateService.instant('JSONFILETYPEERRROR'));
240         } else {
241           this.notifierService.notify('error', this.translateService.instant('ERROR'));
242         }
243         this.fileInputNetsLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
244         this.fileInputNets.nativeElement.value = null;
245       });
246     } else if (files && files.length > 1) {
247       this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
248     }
249     this.fileInputNetsLabel.nativeElement.innerText = files[0].name;
250     this.fileInputNets.nativeElement.value = null;
251   }
252
253   /** credentials file process @private */
254   public credentialsFile(files: FileList): void {
255     if (files && files.length === 1) {
256       this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => {
257         const getCredentialsJson: string = jsyaml.load(fileContent, { json: true });
258         // tslint:disable-next-line: no-backbone-get-set-outside-model
259         this.k8sclusterForm.get('credentials').setValue(JSON.stringify(getCredentialsJson));
260       }).catch((err: string): void => {
261         if (err === 'typeError') {
262           this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
263         } else {
264           this.notifierService.notify('error', this.translateService.instant('ERROR'));
265         }
266         this.fileInputCredentialsLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
267         this.fileInputCredentials.nativeElement.value = null;
268       });
269     } else if (files && files.length > 1) {
270       this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
271     }
272     this.fileInputCredentialsLabel.nativeElement.innerText = files[0].name;
273     this.fileInputCredentials.nativeElement.value = null;
274   }
275
276 }