Feature: 11055 Support of several node groups in clusters created by OSM 32/15232/8 v18.0.0 v18.0.1
authorSANDHYA.JS <sandhya.j@tataelxsi.co.in>
Fri, 13 Jun 2025 11:59:35 +0000 (17:29 +0530)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Tue, 22 Jul 2025 14:27:56 +0000 (16:27 +0200)
- Added control plane support in managed post
- When aws vim account is selected paylaod will get differed
- Added details page in clusters to view node and ksu for
  specified cluster
- Fixed Bug 2402 - Unable to create Ns Config template from Ui
  bug by chnaging api

Change-Id: I4eb327fd86b0c4a706b05a8ed10524e4d2c5bc95
Signed-off-by: SANDHYA.JS <sandhya.j@tataelxsi.co.in>
48 files changed:
.eslintrc.json
angular.json
src/app/k8s/K8sModule.ts
src/app/k8s/k8s-action/K8sActionComponent.html
src/app/k8s/k8s-action/K8sActionComponent.ts
src/app/k8s/k8s-add-cluster/K8sAddClusterComponent.html
src/app/k8s/k8s-add-cluster/K8sAddClusterComponent.scss
src/app/k8s/k8s-add-cluster/K8sAddClusterComponent.ts
src/app/k8s/k8s-info/K8sInfoComponent.html [new file with mode: 0644]
src/app/k8s/k8s-info/K8sInfoComponent.scss [new file with mode: 0644]
src/app/k8s/k8s-info/K8sInfoComponent.ts [new file with mode: 0644]
src/app/k8s/k8s-ksu/ksu-add/KSUAddComponent.html
src/app/k8s/k8s-ksu/ksu-add/KSUAddComponent.ts
src/app/k8s/k8s-ksu/ksu-details/KSUComponent.html
src/app/k8s/k8s-ksu/ksu-details/KSUComponent.ts
src/app/k8s/k8s-profile/k8s-app-profile-details/K8sAppProfileComponent.html
src/app/k8s/k8s-profile/k8s-app-profile-details/K8sAppProfileComponent.ts
src/app/k8s/k8s-profile/k8s-infra-config-details/K8sInfraConfigProfileComponent.html
src/app/k8s/k8s-profile/k8s-infra-config-details/K8sInfraConfigProfileComponent.ts
src/app/k8s/k8s-profile/k8s-infra-controller-details/K8sInfraControllerProfileComponent.html
src/app/k8s/k8s-profile/k8s-infra-controller-details/K8sInfraControllerProfileComponent.ts
src/app/k8s/k8s-profile/k8s-resource-profile/K8sResourceProfileComponent.html
src/app/k8s/k8s-profile/k8s-resource-profile/K8sResourceProfileComponent.ts
src/app/k8s/k8scluster/K8sClusterComponent.html
src/app/k8s/k8scluster/K8sClusterComponent.ts
src/app/k8s/node-add/NodeAddComponent.html [new file with mode: 0644]
src/app/k8s/node-add/NodeAddComponent.scss [new file with mode: 0644]
src/app/k8s/node-add/NodeAddComponent.ts [new file with mode: 0644]
src/app/packages/oka-packages/OKAPackageComponent.html
src/app/packages/oka-packages/OKAPackageComponent.ts
src/app/utilities/compose-packages/ComposePackages.html
src/app/utilities/compose-packages/ComposePackages.ts
src/app/utilities/delete/DeleteComponent.html
src/app/utilities/delete/DeleteComponent.ts
src/app/utilities/oka-packages-action/OkaPackagesActionComponent.html
src/app/utilities/show-info/ShowInfoComponent.ts
src/assets/i18n/de.json
src/assets/i18n/en.json
src/assets/i18n/es.json
src/assets/i18n/pt.json
src/environments/environment.prod.ts
src/environments/environment.ts
src/models/CommonModel.ts
src/models/K8sModel.ts
src/models/MenuModel.ts
src/models/VNFDModel.ts
src/services/SharedService.ts
tsconfig.json

index 1e17cd7..ae848d9 100644 (file)
                         "ignore": [
                             -1,
                             0,
-                            1
+                            1,2,3
                         ],
                         "ignoreArrayIndexes": true,
                         "ignoreDefaultValues": true
index 066e675..e9d40e9 100644 (file)
@@ -46,7 +46,8 @@
                             "node_modules/@fortawesome/fontawesome-free/css/all.min.css"
                         ],
                         "scripts": [
-                            "src/assets/js/tar.js"
+                            "src/assets/js/tar.js",
+                            "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
                         ],
                         "stylePreprocessorOptions": {
                             "includePaths": [
index 4b9ff15..913353c 100644 (file)
@@ -35,6 +35,7 @@ import { K8sAppProfileComponent } from 'K8sAppProfileComponent';
 import { K8sAttachProfileComponent } from 'K8sAttachProfileComponent';
 import { K8sClusterComponent } from 'K8sClusterComponent';
 import { K8sComponent } from 'K8sComponent';
+import { K8sInfoComponent } from 'K8sInfoComponent';
 import { K8sInfraConfigAddComponent } from 'K8sInfraConfigAddComponent';
 import { K8sInfraConfigProfileComponent } from 'K8sInfraConfigProfileComponent';
 import { K8sInfraControllerProfileComponent } from 'K8sInfraControllerProfileComponent';
@@ -44,6 +45,7 @@ import { KSUAddComponent } from 'KSUAddComponent';
 import { KSUComponent } from 'KSUComponent';
 import { LoaderModule } from 'LoaderModule';
 import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { NodeAddComponent } from 'NodeAddComponent';
 import { PagePerRowModule } from 'PagePerRowModule';
 import { PageReloadModule } from 'PageReloadModule';
 
@@ -66,6 +68,14 @@ const routes: Routes = [
         },
         component: K8sClusterComponent
       },
+      {
+        path: 'details/:id',
+        data: {
+          breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+            projectInfo, { title: 'PAGE.K8S.MENUK8SCLUSTER', url: '/k8s/cluster' }, { title: '{id}', url: null }]
+        },
+        component: K8sInfoComponent
+      },
       {
         path: 'infra-config-profile',
         data: {
@@ -149,7 +159,9 @@ const routes: Routes = [
     K8sAppProfileComponent,
     K8sResourceProfileComponent,
     KSUComponent,
-    KSUAddComponent
+    KSUAddComponent,
+    K8sInfoComponent,
+    NodeAddComponent,
   ],
   providers: [DataService],
   schemas: [CUSTOM_ELEMENTS_SCHEMA]
index f545606..57f4480 100644 (file)
@@ -16,38 +16,44 @@ 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)
 -->
 <div class="btn-group list action" role="group">
-  <button *ngIf="getK8sType === 'repo' || !isCluster && !isKSU && !isProfile" type="button" class="btn btn-primary"
-    (click)="infoK8s(getK8sType)" placement="top" container="body" ngbTooltip="{{'INFO' | translate}}">
-    <i class="fas fa-info icons list" title="info"></i>
+  <button *ngIf="(isCluster || !isCluster) && !isKSU && !isNode && !isProfile && getK8sType !== 'repo'" type="button"
+    class="btn btn-primary" (click)="nodeK8s()" placement="top" container="body"
+    ngbTooltip="{{'PAGE.K8S.DETAILS' | translate}}" [disabled]="value.state !== 'READY' || !isCluster  ">
+    <i class="fa fa-server" title="details"></i>
   </button>
-  <button *ngIf="isCluster && !isKSU && !isProfile " type="button" class="btn btn-primary" (click)="infoK8s(getK8sType)"
-    placement="top" container="body" ngbTooltip="{{'INFO' | translate}}">
+  <button *ngIf="!isProfile" type="button" class="btn btn-primary" (click)="infoK8s(getK8sType)" placement="top"
+    container="body" ngbTooltip="{{'INFO' | translate}}">
     <i class="fas fa-info icons list" title="info"></i>
   </button>
-  <button *ngIf="(isCluster  || isProfile || isKSU)" type="button" class="btn btn-primary" (click)="deleteK8s(false)"
-    placement="top" container="body" ngbTooltip="{{'DELETE' | translate}}">
+  <button *ngIf="(isCluster  || isProfile || isKSU || isNode)" type="button" class="btn btn-primary"
+    (click)="deleteK8s()" placement="top" container="body" ngbTooltip="{{'DELETE' | translate}}"
+    [disabled]="value.state !== 'READY' && value.state !== 'ERROR'">
     <i class="far fa-trash-alt icons" title="delete"></i>
   </button>
   <button *ngIf="getK8sType === 'repo'" type="button" class="btn btn-primary" (click)="deleteK8s(false)" placement="top"
     container="body" ngbTooltip="{{'DELETE' | translate}}">
     <i class="far fa-trash-alt icons" title="delete"></i>
   </button>
-  <button *ngIf="!isCluster && !isKSU && !isProfile && getK8sType !== 'repo' " type="button" class="btn btn-primary" (click)="deleteK8s(false)" placement="top"
-    container="body" ngbTooltip="{{'DEREGISTER' | translate}}">
+  <button *ngIf="!isCluster && !isKSU && !isProfile && !isNode && getK8sType !== 'repo' " type="button"
+    class="btn btn-primary" (click)="deleteK8s()" placement="top" container="body"
+    [disabled]="value.state !== 'READY' && value.state !== 'ERROR' && value.state !== 'ENABLED' && value.state !== 'DEGRADED'"
+    ngbTooltip="{{'DEREGISTER' | translate}}">
     <i class="fas fa-window-close icons" title="deregister"></i>
   </button>
   <button *ngIf="isProfile" type="button" class="btn btn-primary" placement="top" container="body"
-    (click)="editProfile(getK8sType)" ngbTooltip="{{'PAGE.K8S.EDITPROFILE' | translate}}">
+    (click)="editProfile(getK8sType)" [disabled]="value.state !== 'READY'"
+    ngbTooltip="{{'PAGE.K8S.EDITPROFILE' | translate}}">
     <i class="fa fa-edit icons"></i>
   </button>
-   <button *ngIf="(isCluster  || isProfile || isKSU || !isCluster && getK8sType !== 'repo')" type="button" class="btn btn-primary" (click)="deleteK8s(true)"
-    placement="top" container="body" [disabled]="!isCluster && !isProfile && !isKSU" ngbTooltip="{{'FORCEDELETE' | translate}}">
+  <button *ngIf="(isCluster  || isProfile || isKSU || !isCluster && getK8sType !== 'repo')" type="button"
+    class="btn btn-primary" (click)="deleteK8s(true)" placement="top" container="body"
+    [disabled]="!isCluster && !isProfile && !isKSU" ngbTooltip="{{'FORCEDELETE' | translate}}">
     <i class="fas fa-trash-alt icons text-danger" title="delete"></i>
   </button>
-  <div *ngIf="isCluster || !isCluster && !isKSU && !isProfile && getK8sType !== 'repo' " class="btn-group" placement="bottom-right" ngbDropdown
-    display="dynamic" container="body">
-    <button type="button" class="btn btn-primary" [disabled]="!isCluster || state != 'CREATED'" ngbDropdownToggle placement="top"
-      container="body" ngbTooltip="{{'Attach Profile' | translate}}">
+  <div *ngIf="(isCluster || !isCluster) && !isKSU && !isNode && !isProfile && getK8sType !== 'repo'" class="btn-group"
+    placement="bottom-right" ngbDropdown display="dynamic" container="body">
+    <button type="button" class="btn btn-primary" [disabled]="value.state !== 'READY' || !isCluster" ngbDropdownToggle
+      placement="top" container="body" ngbTooltip="{{'Attach Profile' | translate}}">
       <i class="fas fa-link"></i>
     </button>
     <div class="dropdown-menu list-action-dropdown" ngbDropdownMenu>
@@ -70,19 +76,20 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
       </button>
     </div>
   </div>
-  <div *ngIf="((isCluster || !isCluster)&& !isKSU && !isProfile && getK8sType !== 'repo'  )" class="btn-group" ngbDropdown display="dynamic" container="body">
-    <button type="button" [disabled]="!isCluster || state != 'CREATED'" class="btn btn-primary dropdown-toggle action-button"
-      ngbDropdownToggle>
+  <div *ngIf="(isCluster || !isCluster) && !isKSU && !isNode && !isProfile && getK8sType !== 'repo'" class="btn-group"
+    ngbDropdown display="dynamic" container="body">
+    <button type="button" [disabled]="(value.state !== 'READY' || !isCluster)"
+      class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle>
       {{'ACTION' | translate}}
     </button>
     <div class="dropdown-menu list-action-dropdown" ngbDropdownMenu>
       <button *ngIf="isCluster" type="button" class="btn btn-primary dropdown-item" placement="left"
-        (click)="editCluster('update')" container="body" ngbTooltip="{{'PAGE.K8S.UPDATECLUSTER' | translate}}">
-        <i class="fa fa-edit icons"></i> {{'PAGE.K8S.UPDATECLUSTER' | translate}}
+        (click)="editCluster('upgrade')" container="body" ngbTooltip="{{'Version Upgrade' | translate}}">
+        <i class="fa fa-arrow-up"></i> {{'PAGE.K8S.VERSIONUPGRADE' | translate}}
       </button>
       <button *ngIf="isCluster" type="button" class="btn btn-primary dropdown-item" placement="left"
-        (click)="editCluster('upgrade')" container="body" ngbTooltip="{{'PAGE.K8S.UPGRADECLUSTER' | translate}}">
-        <i class="fa fa-arrow-up"></i> {{'PAGE.K8S.UPGRADECLUSTER' | translate}}
+        (click)="editCluster('update')" container="body" ngbTooltip="{{'Update Cluster' | translate}}">
+        <i class="fas fa-arrows-alt-h"></i> {{'PAGE.K8S.UPDATECLUSTER' | translate}}
       </button>
       <button *ngIf="isCluster" type="button" class="btn btn-primary dropdown-item" placement="left"
         (click)="getCredentials()" container="body" ngbTooltip="{{'PAGE.K8S.GETCREDENTIALS' | translate}}">
@@ -91,7 +98,8 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
     </div>
   </div>
   <div *ngIf="isKSU" class="btn-group" ngbDropdown display="dynamic" container="body">
-    <button type="button" class="btn btn-primary dropdown-toggle action-button" [disabled]="state != 'CREATED'" ngbDropdownToggle>
+    <button type="button" class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle
+      [disabled]="value.state !== 'READY'">
       {{'ACTION' | translate}}
     </button>
     <div class="dropdown-menu list-action-dropdown" ngbDropdownMenu>
@@ -109,4 +117,20 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
       </button>
     </div>
   </div>
+  <div *ngIf="isNode" class="btn-group" ngbDropdown display="dynamic" container="body">
+    <button type="button" class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle
+      [disabled]="value.state !== 'READY'">
+      {{'ACTION' | translate}}
+    </button>
+    <div class="dropdown-menu list-action-dropdown" ngbDropdownMenu>
+      <button type="button" class="btn btn-primary dropdown-item" placement="left" (click)="scaling('k8s-scale')"
+        container="body" ngbTooltip="{{'PAGE.K8S.K8SSCALING' | translate}}">
+        <i class="fas fa-arrows-alt-v"></i> {{'PAGE.K8S.K8SSCALING' | translate}}
+      </button>
+      <button type="button" class="btn btn-primary dropdown-item" placement="left" (click)="scaling('edit-node')"
+        container="body" ngbTooltip="{{'EDIT' | translate}}">
+        <i class="fa fa-arrow-up"></i> {{'EDIT' | translate}}
+      </button>
+    </div>
+  </div>
   <app-loader [waitingMessage]="message" *ngIf="isLoadingDownloadResult"></app-loader>
\ No newline at end of file
index 919dda1..0728381 100644 (file)
@@ -20,6 +20,7 @@
  */
 import { HttpHeaders } from '@angular/common/http';
 import { ChangeDetectorRef, Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
 import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
 import { TranslateService } from '@ngx-translate/core';
 import { NotifierService } from 'angular-notifier';
@@ -31,6 +32,7 @@ import { K8sAttachProfileComponent } from 'K8sAttachProfileComponent';
 import { K8sInfraConfigAddComponent } from 'K8sInfraConfigAddComponent';
 import { INFRACONFIGPAYLOAD, K8SCLUSTERDATADISPLAY, K8SPayload, K8SREPODATADISPLAY } from 'K8sModel';
 import { KSUAddComponent } from 'KSUAddComponent';
+import { NodeAddComponent } from 'NodeAddComponent';
 import { RestService } from 'RestService';
 import { isNullOrUndefined, SharedService } from 'SharedService';
 import { ShowInfoComponent } from 'ShowInfoComponent';
@@ -72,6 +74,9 @@ export class K8sActionComponent {
   /** Check cluster or not @public */
   public isCluster = false;
 
+  /** Check node group or not @public */
+  public isNode = false;
+
   /** Check the loading results for loader status @public */
   public isLoadingDownloadResult: boolean = false;
 
@@ -82,7 +87,10 @@ export class K8sActionComponent {
   private sharedService: SharedService;
 
   /** Contains instance ID @private */
-  private instanceID: string;
+  private k8sID: string;
+
+  /** Contains instance name @private */
+  private k8sName: string;
 
   /** Utilizes rest service for any CRUD operations @private */
   private restService: RestService;
@@ -100,6 +108,9 @@ export class K8sActionComponent {
   /** Controls the header form @private */
   private headers: HttpHeaders;
 
+  /** Holds teh instance of AuthService class of type AuthService @private */
+  private router: Router;
+
   constructor(injector: Injector) {
     this.injector = injector;
     this.modalService = this.injector.get(NgbModal);
@@ -108,6 +119,7 @@ export class K8sActionComponent {
     this.translateService = this.injector.get(TranslateService);
     this.restService = this.injector.get(RestService);
     this.cd = this.injector.get(ChangeDetectorRef);
+    this.router = this.injector.get(Router);
   }
 
   /**
@@ -118,7 +130,8 @@ export class K8sActionComponent {
       Accept: 'application/zip, application/json',
       'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
     });
-    this.instanceID = this.value.identifier;
+    this.k8sID = this.value.identifier;
+    this.k8sName = this.value.name;
     this.getK8sType = this.value.pageType;
     this.state = this.value.state;
     if ((this.value.createdbyosm) === 'true') {
@@ -137,6 +150,12 @@ export class K8sActionComponent {
     } else {
       this.isProfile = false;
     }
+
+    if (this.value.pageType === 'node') {
+      this.isNode = true;
+    } else {
+      this.isNode = false;
+    }
   }
 
   /** Delete User Account @public */
@@ -155,6 +174,13 @@ export class K8sActionComponent {
     });
   }
 
+  /** Details page @public */
+  public nodeK8s(): void {
+    this.router.navigate(['/k8s/details/' + this.k8sID]).catch((): void => {
+      // Catch Navigation Error
+    });
+  }
+
   /** Shows information using modalservice @public */
   public infoK8s(pageType: string): void {
     let pageName: string = '';
@@ -162,18 +188,26 @@ export class K8sActionComponent {
     if (pageType === 'repo') {
       pageName = 'k8s-repo';
       title = 'PAGE.K8S.K8SREPODETAILS';
+    } else if (pageType === 'node') {
+      pageName = 'k8s-node';
+      title = 'Node Details';
+    } else if (pageType === 'k8-ksu') {
+      pageName = 'k8s-ksu';
+      title = 'KSU Details';
     } else {
       pageName = 'k8s-cluster';
       title = 'PAGE.K8S.K8SCLUSTERDETAILS';
     }
     // eslint-disable-next-line security/detect-non-literal-fs-filename
     this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
-      id: this.instanceID,
+      id: this.k8sID,
       page: pageName,
       titleName: title,
       createdbyosm: this.value.createdbyosm,
       bootstrap: this.value.bootstrap,
-      key: this.value.key
+      key: this.value.key,
+      cluster_mode: this.value.cluster_mode,
+      cluster_id: this.value.cluster_id
     };
   }
   /** Edit profile @public */
@@ -208,6 +242,22 @@ export class K8sActionComponent {
     });
   }
 
+  /** Handle Scaling @public */
+  public scaling(editType: string): void {
+    // eslint-disable-next-line security/detect-non-literal-fs-filename
+    const modalRef: NgbModalRef = this.modalService.open(NodeAddComponent, { backdrop: 'static' });
+    modalRef.componentInstance.profileID = this.value.identifier;
+    modalRef.componentInstance.clusterId = this.value.cluster_id;
+    modalRef.componentInstance.profileType = editType;
+    modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+      if (result) {
+        this.sharedService.callData();
+      }
+    }).catch((): void => {
+      // Catch Navigation Error
+    });
+  }
+
 
   /** Edit profile under cluster @public */
   public editClusterProfile(editType: string): void {
@@ -261,10 +311,10 @@ export class K8sActionComponent {
       headers: this.headers,
       responseType: 'blob'
     };
-    this.restService.getResource(environment.K8SCREATECLUSTER_URL + '/' + this.instanceID + '/get_creds')
+    this.restService.getResource(environment.K8SCREATECLUSTER_URL + '/' + this.k8sID + '/get_creds')
       .subscribe((res: { op_id: string }) => {
         if (!isNullOrUndefined(res.op_id)) {
-          this.restService.getResource(environment.K8SCREATECLUSTER_URL + '/' + this.instanceID + '/get_creds_file' + '/' + res.op_id, httpOptions)
+          this.restService.getResource(environment.K8SCREATECLUSTER_URL + '/' + this.k8sID + '/get_creds_file' + '/' + res.op_id, httpOptions)
             .subscribe((response: Blob) => {
               this.isLoadingDownloadResult = true;
               if (!isNullOrUndefined(response)) {
index e9ac743..73f1038 100644 (file)
@@ -15,7 +15,7 @@ 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)
 -->
-<form [formGroup]="k8sclusterForm" (ngSubmit)="k8sAddClusterSubmit();">
+<form [formGroup]="k8sclusterForm" (ngSubmit)="k8sAddClusterSubmit();" (keydown.enter)="$event.preventDefault()">
   <div class="modal-header">
     <h4 *ngIf="profileType === 'Register'" class="modal-title" id="modal-basic-title">{{'PAGE.K8S.REGISTERCLUSTER' |
       translate}}
@@ -23,7 +23,7 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
     <h4 *ngIf="profileType === 'Manage'" class="modal-title" id="modal-basic-title">{{'PAGE.K8S.CREATECLUSTER' |
       translate}}
     </h4>
-    <h4 *ngIf="profileType === 'upgrade'" class="modal-title" id="modal-basic-title">{{'PAGE.K8S.UPGRADECLUSTER' |
+    <h4 *ngIf="profileType === 'upgrade'" class="modal-title" id="modal-basic-title">{{'PAGE.K8S.VERSIONUPGRADE' |
       translate}}
     </h4>
     <h4 *ngIf="profileType === 'update'" class="modal-title" id="modal-basic-title">{{'PAGE.K8S.UPDATECLUSTER' |
@@ -33,7 +33,8 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
       <i class="fas fa-times-circle text-danger"></i>
     </button>
   </div>
-  <div class="modal-body modal-body-custom-height">
+  <div class="modal-body modal-body-custom-height"
+    *ngIf="profileType === 'Manage' || profileType === 'Register' || isChecked || profileType === 'upgrade'">
     <div class="form-group row mb-3" *ngIf="profileType === 'Manage' || profileType === 'Register'">
       <div class="col-sm-12">
         <label class="form-check-label">
@@ -71,6 +72,15 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
           required>
       </div>
     </div>
+    <div class="form-group row mb-3"
+      *ngIf="profileType === 'Manage' || profileType === 'Register' || !isChecked || profileType === 'update'">
+      <label class="col-sm-4 col-form-label" for="description">{{'PAGE.K8S.DESCRIPTION' | translate}}</label>
+      <div class="col-sm-8">
+        <textarea class="form-control" placeholder="{{'PAGE.K8S.DESCRIPTION' | translate}}" type="text"
+          formControlName="description" id="description"
+          [ngClass]="{ 'is-invalid': submitted && f.description.errors }"></textarea>
+      </div>
+    </div>
     <div class="form-group row mb-3" *ngIf="profileType === 'Manage' || profileType === 'Register' || !isChecked">
       <label class="col-sm-4 col-form-label" for="vim_account">{{'PAGE.K8S.VIMACCOUNT' | translate}}*</label>
       <div class="col-sm-8">
@@ -81,6 +91,45 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
         </ng-select>
       </div>
     </div>
+    <div class="form-group row mb-3" *ngIf=" vimType === 'aws' && profileType === 'Manage'">
+      <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.ROLENAME' | translate}}</label>
+      <div class="col-sm-8">
+        <input autocomplete="off" class="form-control" placeholder="{{'arn:aws:iam::[account-id]:role/[role-name]' | translate}}" type="text"
+          formControlName="iam_role" id="iam_role" [ngClass]="{ 'is-invalid': submitted && f.iam_role.errors }">
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf=" vimType === 'aws' && profileType === 'Manage'">
+      <label class="col-sm-4 col-form-label" for="private_subnet">{{ 'PAGE.K8S.PRIVATESUBNET' | translate }}</label>
+      <div class="col-sm-8">
+        <div class="chip-input-container">
+          <div formArrayName="private_subnet" class="chips-wrapper">
+            <span class="chip" *ngFor="let chip of chipsprivateArray.controls; let i = index">
+              {{ chip.value }}
+              <button type="button" (click)="removeprivateChip(i)">x</button>
+            </span>
+            <input #inputField autocomplete="off" class="form-control chip-input" id="private_subnet"
+              (keyup.enter)="addprivateChips()" (keydown.backspace)="removeprivateLastChip($event)"
+              placeholder="Type and press Enter">
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf=" vimType === 'aws' && profileType === 'Manage'">
+      <label class="col-sm-4 col-form-label" for="public_subnet">{{ 'PAGE.K8S.PUBLICSUBNET' | translate }}</label>
+      <div class="col-sm-8">
+        <div class="chip-input-container">
+          <div formArrayName="public_subnet" class="chips-wrapper">
+            <span class="chip" *ngFor="let chip of chipspublicArray.controls; let i = index">
+              {{ chip.value }}
+              <button type="button" (click)="removepublicChip(i)">x</button>
+            </span>
+            <input #inputField autocomplete="off" class="form-control chip-input" id="public_subnet"
+              (keyup.enter)="addpublicChips()" (keydown.backspace)="removepublicLastChip($event)"
+              placeholder="Type and press Enter">
+          </div>
+        </div>
+      </div>
+    </div>
     <div class="form-group row mb-3" *ngIf="!isChecked && profileType === 'Register'">
       <label class="col-sm-4 col-form-label" for="deployment_methods">{{'PAGE.K8S.DEPLOYMENTMETHODS' |
         translate}}*</label>
@@ -92,14 +141,6 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
         </ng-select>
       </div>
     </div>
-    <div class="form-group row mb-3" *ngIf="profileType === 'Manage' || profileType === 'Register' || !isChecked || profileType === 'update'">
-      <label class="col-sm-4 col-form-label" for="description">{{'PAGE.K8S.DESCRIPTION' | translate}}</label>
-      <div class="col-sm-8">
-        <textarea class="form-control" placeholder="{{'PAGE.K8S.DESCRIPTION' | translate}}" type="text"
-          formControlName="description" id="description"
-          [ngClass]="{ 'is-invalid': submitted && f.description.errors }"></textarea>
-      </div>
-    </div>
     <div class="form-group row mb-3" *ngIf="!isChecked && profileType === 'Register'">
       <label class="col-sm-4 col-form-label" for="nets">{{'PAGE.K8S.NETS' | translate}}*</label>
       <div class="col-sm-8">
@@ -125,7 +166,7 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
         </div>
       </div>
     </div>
-    <div class="form-group row mb-3" *ngIf="profileType === 'Manage'">
+    <div class="form-group row mb-3" *ngIf="vimType === 'aws' && profileType === 'Manage'">
       <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.REGIONNAME' | translate}}</label>
       <div class="col-sm-8">
         <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.REGIONNAME' | translate}}" type="text"
@@ -133,7 +174,7 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
           [ngClass]="{ 'is-invalid': submitted && f.region_name.errors }">
       </div>
     </div>
-    <div class="form-group row mb-3" *ngIf="profileType === 'Manage'">
+    <div class="form-group row mb-3" *ngIf="profileType === 'Manage' && vimType !== 'aws' ">
       <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.RESOURCEGROUP' | translate}}</label>
       <div class="col-sm-8">
         <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.RESOURCEGROUP' | translate}}"
@@ -141,20 +182,18 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
           [ngClass]="{ 'is-invalid': submitted && f.resource_group.errors }">
       </div>
     </div>
-    <div class="form-group row mb-3" *ngIf="profileType === 'Manage'">
-      <label class="col-sm-4 col-form-label" for="node_count">{{'PAGE.K8S.NODECOUNT' | translate}}*</label>
+    <div class="form-group row mb-3" *ngIf="profileType === 'Manage' && vimType !== 'aws' ">
+      <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.NODESIZE' | translate}}*</label>
       <div class="col-sm-8">
-        <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.NODECOUNT' | translate}}" type="text"
-          formControlName="node_count" id="node_count" [ngClass]="{ 'is-invalid': submitted && f.node_count.errors }"
-          required>
+        <input autocomplete="off" class="form-control" placeholder="{{'Node Size' | translate}}" type="text"
+          formControlName="node_size" id="node_size" [ngClass]="{ 'is-invalid': submitted && f.node_size.errors }">
       </div>
     </div>
-    <div class="form-group row mb-3" *ngIf="profileType === 'Manage'">
-      <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.NODESIZE' | translate}}*</label>
+    <div class="form-group row mb-3" *ngIf="profileType === 'Manage' && vimType !== 'aws'">
+      <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.NODECOUNT' | translate}}*</label>
       <div class="col-sm-8">
-        <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.NODESIZE' | translate}}" type="text"
-          formControlName="node_size" id="k8s_version" [ngClass]="{ 'is-invalid': submitted && f.node_size.errors }"
-          required>
+        <input autocomplete="off" class="form-control" placeholder="{{'Node Count' | translate}}" type="text"
+          formControlName="node_count" id="node_count" [ngClass]="{ 'is-invalid': submitted && f.node_count.errors }">
       </div>
     </div>
     <div class="form-group row mb-3" *ngIf="profileType === 'upgrade'">
@@ -169,9 +208,7 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
     <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
     <button *ngIf="profileType === 'Manage'" type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
     <button *ngIf="profileType === 'Register'" type="submit" class="btn btn-primary">{{'REGISTER' | translate}}</button>
-    <button *ngIf="profileType === 'upgrade'|| profileType === 'update'"
-      type="submit" class="btn btn-primary">{{'APPLY'
-      | translate}}</button>
+    <button *ngIf="profileType === 'upgrade' || profileType === 'update'" type="submit" class="btn btn-primary">{{'APPLY'| translate}}</button>
   </div>
 </form>
 <app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
index 8885be8..1fd08a8 100644 (file)
 @import "../../../assets/scss/variable.scss";
 @import "../../../assets/scss/mixins/mixin";
 .quotacheck {
-   box-shadow: none;
-   border-radius: 2px;
-   border-color: $gray-600;
+  box-shadow: none;
+  border-radius: 2px;
+  border-color: $gray-600;
 }
 .form-check {
-   padding-left: 30px;
+  padding-left: 30px;
 }
 .quotaCheck-label {
-   position: absolute;
-   left: 26px;
+  position: absolute;
+  left: 26px;
 }
 .tooltip-icon {
-   position: relative;
-   margin-left: 5px;
-   cursor: pointer;
- }
- .tooltip-icon .tooltip-text {
-   visibility: hidden;
-   width: 200px;
-   background-color: #fff;
-   color: #555;
-   text-align: center;
-   padding: 5px 10px;
-   border-radius: 4px;
-   @include border(all, 1, solid, $gray-300);
-   z-index: 1;
-   bottom: 125%;
-   left: 50%;
-   transform: translateX(-50%);
-   opacity: 0;
-   transition: opacity 0.3s;
- }
- .tooltip-icon:hover .tooltip-text {
-   visibility: visible;
-   opacity: 1;
- }
\ No newline at end of file
+  position: relative;
+  margin-left: 5px;
+  cursor: pointer;
+}
+.tooltip-icon .tooltip-text {
+  visibility: hidden;
+  width: 200px;
+  background-color: #fff;
+  color: #555;
+  text-align: center;
+  padding: 5px 10px;
+  border-radius: 4px;
+  @include border(all, 1, solid, $gray-300);
+  z-index: 1;
+  bottom: 125%;
+  left: 50%;
+  transform: translateX(-50%);
+  opacity: 0;
+  transition: opacity 0.3s;
+}
+.tooltip-icon:hover .tooltip-text {
+  visibility: visible;
+  opacity: 1;
+}
+.chip-input-container {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  border: 1px solid #e9ecef;
+  padding: 5px;
+  border-radius: 5px;
+  min-height: 38px;
+  width: 100%;
+  position: relative;
+  box-sizing: border-box;
+}
+.chip-input-container:focus-within {
+  border: 1px solid #afb5c1;
+  background-color: #f2f4f5;
+}
+.chips-wrapper {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  gap: 5px;
+  width: 100%;
+}
+.chip {
+  background: #007bff;
+  color: white;
+  padding: 5px 10px;
+  border-radius: 15px;
+  font-size: 14px;
+  display: flex;
+  align-items: center;
+  height: 28px;
+  white-space: nowrap;
+}
+.chip button {
+  background: none;
+  border: none;
+  color: white;
+  margin-left: 5px;
+  cursor: pointer;
+  font-size: 14px;
+}
+.chip-input {
+  border: none;
+  outline: none;
+  flex: 1;
+  min-width: 100px;
+  height: 28px;
+  padding: 4px;
+  background: transparent;
+}
\ No newline at end of file
index 34ceeab..69fe54f 100644 (file)
@@ -20,7 +20,7 @@
  */
 import { HttpHeaders } from '@angular/common/http';
 import { Component, ElementRef, Injector, Input, OnInit, ViewChild } from '@angular/core';
-import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
 import { TranslateService } from '@ngx-translate/core';
 import { NotifierService } from 'angular-notifier';
@@ -51,6 +51,9 @@ export class K8sAddClusterComponent implements OnInit {
   /** Contains all vim account collections */
   public vimAccountSelect: VimAccountDetails;
 
+  /** Contains selected vim */
+  public vimType: string;
+
   /** Input contains Modal dialog component Instance @public */
   @Input() public profileType: string;
 
@@ -163,7 +166,7 @@ export class K8sAddClusterComponent implements OnInit {
   public k8sclusterFormAction(): void {
     this.k8sclusterForm = this.formBuilder.group({
       name: ['', [Validators.required]],
-      k8s_version: ['', [Validators.required]],
+      k8s_version: [''],
       vim_account: [null, [Validators.required]],
       description: [''],
       nets: ['', [Validators.required]],
@@ -175,6 +178,9 @@ export class K8sAddClusterComponent implements OnInit {
       node_size: ['', [Validators.required]],
       bootstrap: [true],
       k8sVersion: ['', [Validators.required]],
+      iam_role: [''],
+      private_subnet: this.formBuilder.array([]),
+      public_subnet: this.formBuilder.array([]),
       update: ['']
     });
   }
@@ -182,6 +188,65 @@ export class K8sAddClusterComponent implements OnInit {
   /** convenience getter for easy access to form fields */
   get f(): FormGroup['controls'] { return this.k8sclusterForm.controls; }
 
+  /** convenience getter for easy access to form array privatesubnet */
+  get chipsprivateArray(): FormArray {
+    return this.k8sclusterForm.get('private_subnet') as FormArray;
+  }
+
+  /** To add privatesubnet chips */
+  public addprivateChips() {
+    const input = document.getElementById('private_subnet') as HTMLInputElement;
+    const value = input.value.trim();
+
+    if (value) {
+      this.chipsprivateArray.push(new FormControl(value));
+      input.value = '';
+    }
+  }
+  /** convenience getter for easy access to form array publicsubnet */
+  get chipspublicArray(): FormArray {
+    return this.k8sclusterForm.get('public_subnet') as FormArray;
+  }
+
+  /** To add publicsubnet chips */
+  public addpublicChips() {
+    const input = document.getElementById('public_subnet') as HTMLInputElement;
+    const value = input.value.trim();
+
+    if (value) {
+      this.chipspublicArray.push(new FormControl(value));
+      input.value = '';
+    }
+  }
+
+  /** To remove privatesubnet chips */
+  public removeprivateChip(index: number) {
+    this.chipsprivateArray.removeAt(index);
+  }
+
+  /** To remove privatesubnet last chip */
+  public removeprivateLastChip(event: KeyboardEvent) {
+    const input = event.target as HTMLInputElement;
+    if (event.key === 'Backspace' && input.value === '' && this.chipsprivateArray.length > 0) {
+      this.chipsprivateArray.removeAt(this.chipsprivateArray.length - 1); // Remove last chip if input is empty
+      event.preventDefault();
+    }
+  }
+  /** To remove publicsubnet chips */
+  public removepublicChip(index: number) {
+    this.chipspublicArray.removeAt(index);
+  }
+
+  /** To remove publicsubnet last chip */
+  public removepublicLastChip(event: KeyboardEvent) {
+    const input = event.target as HTMLInputElement;
+    if (event.key === 'Backspace' && input.value === '' && this.chipspublicArray.length > 0) {
+      this.chipspublicArray.removeAt(this.chipspublicArray.length - 1); // Remove last chip if input is empty
+      event.preventDefault();
+    }
+  }
+
+
   /** Call the vimAccount details in the selection options @public */
   public getDetailsvimAccount(): void {
     this.isLoadingResults = true;
@@ -219,6 +284,7 @@ export class K8sAddClusterComponent implements OnInit {
   /** Contain selected vimAccount details @public */
   public getDetailsvim(event: VimAccountDetails): void {
     this.vimAccountId = event._id;
+    this.vimType = event.vim_type;
   }
 
   /** On modal submit k8sAddClusterSubmit will called @public */
@@ -229,6 +295,23 @@ export class K8sAddClusterComponent implements OnInit {
       this.getFormControl('deployment_methods').disable();
       this.getFormControl('k8sVersion').disable();
       this.getFormControl('update').disable();
+      this.clusterUrl = environment.K8SCREATECLUSTER_URL;
+      if (this.vimType === 'aws') {
+        this.getFormControl('resource_group').disable();
+        this.getFormControl('k8sVersion').disable();
+        this.getFormControl('node_size').disable();
+        this.getFormControl('node_count').disable();
+        this.getFormControl('nets').disable();
+        this.getFormControl('credentials').disable();
+        this.getFormControl('update').disable();
+        this.getFormControl('deployment_methods').disable();
+      } else if (this.vimType !== 'aws') {
+        this.getFormControl('nets').disable();
+        this.getFormControl('credentials').disable();
+        this.getFormControl('deployment_methods').disable();
+        this.getFormControl('k8sVersion').disable();
+        this.getFormControl('update').disable();
+      }
       this.manageCluster();
     } else if (this.profileType === 'Register' && this.isChecked === true) {
       this.clusterUrl = environment.K8SCREATECLUSTER_URL + '/register';
@@ -240,6 +323,9 @@ export class K8sAddClusterComponent implements OnInit {
       this.getFormControl('nets').disable();
       this.getFormControl('deployment_methods').disable();
       this.getFormControl('k8sVersion').disable();
+      this.getFormControl('iam_role').disable();
+      this.getFormControl('private_subnet').disable();
+      this.getFormControl('public_subnet').disable();
       this.getFormControl('update').disable();
       this.registerCluster();
     } if (this.isChecked === false && this.profileType === 'Register') {
@@ -250,6 +336,9 @@ export class K8sAddClusterComponent implements OnInit {
       this.getFormControl('node_count').disable();
       this.getFormControl('node_size').disable();
       this.getFormControl('k8sVersion').disable();
+      this.getFormControl('iam_role').disable();
+      this.getFormControl('private_subnet').disable();
+      this.getFormControl('public_subnet').disable();
       this.getFormControl('update').disable();
       this.oldregisterCluster();
     } else if (this.profileType === 'upgrade') {
@@ -265,7 +354,9 @@ export class K8sAddClusterComponent implements OnInit {
       this.getFormControl('bootstrap').disable();
       this.getFormControl('node_count').disable();
       this.getFormControl('node_size').disable();
-      this.getFormControl('k8s_version').disable();
+      this.getFormControl('iam_role').disable();
+      this.getFormControl('private_subnet').disable();
+      this.getFormControl('public_subnet').disable();
       this.getFormControl('update').disable();
       this.updateCluster();
     } else if (this.profileType === 'update') {
@@ -281,8 +372,10 @@ export class K8sAddClusterComponent implements OnInit {
       this.getFormControl('node_size').disable();
       this.getFormControl('k8s_version').disable();
       this.getFormControl('k8sVersion').disable();
+      this.getFormControl('iam_role').disable();
+      this.getFormControl('private_subnet').disable();
+      this.getFormControl('public_subnet').disable();
       this.getFormControl('name').disable();
-
       this.editCluster();
     }
   }
@@ -375,7 +468,6 @@ export class K8sAddClusterComponent implements OnInit {
     if (this.k8sclusterForm.value.description === '') {
       delete this.k8sclusterForm.value.description;
     }
-
     const apiURLHeader: APIURLHEADER = {
       url: this.clusterUrl,
       httpOptions: { headers: this.headers }
@@ -393,7 +485,7 @@ export class K8sAddClusterComponent implements OnInit {
     });
   }
 
-  /** Manage cluster @public */
+  /** controlplane cluster flow @public */
   public manageCluster(): void {
     this.submitted = true;
     this.sharedService.cleanForm(this.k8sclusterForm);
@@ -404,36 +496,51 @@ export class K8sAddClusterComponent implements OnInit {
       message: 'Done'
     };
     const apiURLHeader: APIURLHEADER = {
-      url: environment.K8SCREATECLUSTER_URL,
+      url: this.clusterUrl,
       httpOptions: { headers: this.headers }
     };
 
     this.isLoadingResults = true;
-    const payload: K8SPayload = {
-      name: this.k8sclusterForm.value.name,
-      vim_account: this.k8sclusterForm.value.vim_account,
-      location: this.k8sclusterForm.value.location,
-      region_name: this.k8sclusterForm.value.region_name,
-      resource_group: this.k8sclusterForm.value.resource_group,
-      k8s_version: this.k8sclusterForm.value.k8s_version,
-      node_size: this.k8sclusterForm.value.node_size,
-      node_count: Number(this.k8sclusterForm.value.node_count),
-      description: this.k8sclusterForm.value.description,
-      bootstrap: Boolean(this.k8sclusterForm.value.bootstrap)
-    };
-    if (this.k8sclusterForm.value.region_name === '') {
-      delete payload.region_name;
-    } else if (this.k8sclusterForm.value.resource_group === '') {
-      delete payload.resource_group;
-    } else if (this.k8sclusterForm.value.description === '') {
-      delete payload.description;
+    const formData = this.k8sclusterForm.value;
+    if (this.k8sclusterForm.value.private_subnet.length <= 0) {
+      delete this.k8sclusterForm.value.private_subnet;
     }
-    if (this.k8sclusterForm.value.region_name === '' && this.k8sclusterForm.value.resource_group === '' && this.k8sclusterForm.value.description === '') {
-      delete payload.region_name;
-      delete payload.resource_group;
-      delete payload.description;
+    if (this.k8sclusterForm.value.public_subnet.length <= 0) {
+      delete this.k8sclusterForm.value.public_subnet;
     }
-    this.restService.postResource(apiURLHeader, payload).subscribe((result: {}) => {
+    if (this.vimType !== 'aws') {
+      this.payload = {
+        name: this.k8sclusterForm.value.name,
+        vim_account: this.k8sclusterForm.value.vim_account,
+        location: this.k8sclusterForm.value.location,
+        region_name: this.k8sclusterForm.value.region_name,
+        resource_group: this.k8sclusterForm.value.resource_group,
+        k8s_version: this.k8sclusterForm.value.k8s_version,
+        node_size: this.k8sclusterForm.value.node_size,
+        node_count: Number(this.k8sclusterForm.value.node_count),
+        description: this.k8sclusterForm.value.description,
+        bootstrap: Boolean(this.k8sclusterForm.value.bootstrap)
+      };
+      if (this.k8sclusterForm.value.region_name === '') {
+        delete this.payload.region_name;
+      }
+      if (this.k8sclusterForm.value.resource_group === '') {
+        delete this.payload.resource_group;
+      }
+      if (this.k8sclusterForm.value.description === '') {
+        delete this.payload.description;
+      }
+    } else {
+      this.payload = Object.keys(formData).reduce((acc, key) => {
+        // eslint-disable-next-line security/detect-object-injection
+        if (formData[key] !== null && formData[key] !== undefined && formData[key] !== '') {
+          // eslint-disable-next-line security/detect-object-injection
+          acc[key] = formData[key];
+        }
+        return acc;
+      }, {});
+    }
+    this.restService.postResource(apiURLHeader, this.payload).subscribe((result: {}) => {
       this.activeModal.close(modalData);
       this.isLoadingResults = false;
       this.notifierService.notify('success', this.k8sclusterForm.value.name +
@@ -475,8 +582,7 @@ export class K8sAddClusterComponent implements OnInit {
     });
   }
 
-
-  /** Update cluster @public */
+  /** Edit cluster @public */
   public editCluster(): void {
     this.submitted = true;
     this.sharedService.cleanForm(this.k8sclusterForm);
diff --git a/src/app/k8s/k8s-info/K8sInfoComponent.html b/src/app/k8s/k8s-info/K8sInfoComponent.html
new file mode 100644 (file)
index 0000000..4bf3783
--- /dev/null
@@ -0,0 +1,248 @@
+<!--
+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: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+-->
+<div class="d-flex flex-row justify-content-between">
+    <div class="col-sm-8 mb-3">
+        <div class="d-flex align-items-center header-style">{{clusterName}}</div>
+    </div>
+</div>
+<div class="btn-group list action" role="group">
+    <button type="button" class="btn btn-block border-0 bg-light collapse text-dark"
+        [ngClass]="{'active': activeButton === 1}" (click)="setActiveButton(1)">
+        <span class="circle">{{(node_count)?node_count:0}}</span>
+        <p>{{'PAGE.K8S.NODE' | translate}}</p>
+    </button>
+    <button type="button" class="btn btn-block border-0 bg-light collapse text-dark"
+        [ngClass]="{'active': activeButton === 2}" (click)="setActiveButton(2)">
+        <span class="circle">{{(ksu_count)?ksu_count:0}}</span>
+        <p>{{'PAGE.K8S.KSU' | translate}}</p>
+    </button>
+</div>
+<div id="demo" class="collapse context-style p-2" *ngIf="isCollapsed2 === true">
+    <div class="container">
+        <span class="button  d-flex justify-content-end">
+            <button class="btn btn-primary mb-2 me-2" type="button" placement="top" container="body"
+                ngbTooltip="{{'Add KSU' | translate}}" (click)="addK8sCluster('card_ksu')">
+                <i class="fas fa-plus-circle" aria-hidden="true"></i>&nbsp; {{'PAGE.K8S.ADDKSU' | translate}}
+            </button>
+        </span>
+        <div class="row info gx-3" *ngIf="ksu_count !== 0 else noData">
+            <div *ngFor="let item of ksuDetail" class="col-12 col-sm-4 col-md-4 col-lg-4 col-xl-4 mb-3">
+                <ng-container *ngIf="item?.package_name.length > 1; else singleCard">
+                    <ngb-carousel class="card-carousel" [interval]="0" wrap="true">
+                        <ng-template ngbSlide *ngFor="let pkg of item?.package_name; let i = index">
+                            <div class="custom-card card">
+                                <div class="card-header custom-card-header d-flex justify-content-between">
+                                    <b style="font-size:medium;">{{ item.name }}</b>
+                                    <span>
+                                        <i *ngIf="item.state === 'READY'" class="fas fa-check-circle text-success"
+                                            data-bs-toggle="tooltip" title="READY"></i>
+                                        <i *ngIf="item.state.startsWith('IN_PROGRESS')"
+                                            class="fas fa-spinner text-warning" data-bs-toggle="tooltip"
+                                            title="{{ item.state }}"></i>
+                                        <i *ngIf="item.state === 'ERROR'" class="fas fa-times-circle text-danger"
+                                            data-bs-toggle="tooltip" title="ERROR"></i>
+                                    </span>
+                                </div>
+                                <div class="card-body">
+                                    <p class="label-value-pair-description">
+                                        <span class="label1">{{ 'PAGE.K8S.DESCRIPTION' | translate }}:</span>
+                                        <span class="value1">
+                                            <span class="short-description"
+                                                (mouseenter)="showPopover($event, item.description)"
+                                                (mouseleave)="hidePopover()">
+                                                {{ item.description }}
+                                            </span>
+                                            <span class="popover-description" #popover
+                                                *ngIf="isPopoverVisible  && item?.description.length > 15">{{
+                                                popoverText }}</span>
+                                        </span>
+                                    </p>
+                                    <hr>
+                                    <p class="label-value-pair">
+                                        <span class="label">{{ 'PAGE.K8S.PACKAGENAME' | translate }}:</span>
+                                        <span class="value">{{ item?.package_name[i] }}</span>
+                                    </p>
+                                    <p class="label-value-pair">
+                                        <span class="label">{{ 'PAGE.K8S.PACKAGEPATH' | translate }}:</span>
+                                        <span class="value">{{ item?.package_path[i] }}</span>
+                                    </p>
+                                    <p class="label-value-pair">
+                                        <span class="label">{{'MODIFIED' | translate }}:</span>
+                                        <span class="value">{{ item.modified }}</span>
+                                    </p>
+                                </div>
+                                <div class="card-footer">
+                                    <div class="btn-group list" role="group">
+                                        <button type="button" class="btn btn-primary"
+                                            (click)='onView(item.identifier, 2)' placement="top" container="body"
+                                            ngbTooltip="{{'VIEW' | translate}}">
+                                            <i class="fa fa-eye"></i>
+                                        </button>
+                                    </div>
+                                </div>
+                            </div>
+                        </ng-template>
+                    </ngb-carousel>
+                </ng-container>
+                <ng-template #singleCard>
+                    <div class="custom-card card">
+                        <div class="card-header custom-card-header d-flex justify-content-between">
+                            <b style="font-size:medium;">{{ item.name }}</b>
+                            <span>
+                                <i *ngIf="item.state === 'READY'" class="fas fa-check-circle text-success"
+                                    data-bs-toggle="tooltip" title="READY"></i>
+                                <i *ngIf="item.state.startsWith('IN_PROGRESS')" class="fas fa-spinner text-warning"
+                                    data-bs-toggle="tooltip" title="{{ item.state }}"></i>
+                                <i *ngIf="item.state === 'ERROR'" class="fas fa-times-circle text-danger"
+                                    data-bs-toggle="tooltip" title="ERROR"></i>
+                            </span>
+                        </div>
+                        <div class="card-body">
+                            <p class="label-value-pair-description">
+                                <span class="label1">{{ 'PAGE.K8S.DESCRIPTION' | translate}}:</span>
+                                <span class="value1">
+                                    <span class="short-description" (mouseenter)="showPopover($event, item.description)"
+                                        (mouseleave)="hidePopover()">
+                                        {{ item.description }}
+                                    </span>
+                                    <span class="popover-description" #popover *ngIf="isPopoverVisible">{{
+                                        popoverText }}</span>
+                                </span>
+                            </p>
+                            <hr>
+                            <p class="label-value-pair">
+                                <span class="label">{{ 'PAGE.K8S.PACKAGENAME' | translate }}:</span>
+                                <span class="value">{{ item?.package_name[0] }}</span>
+                            </p>
+                            <p class="label-value-pair">
+                                <span class="label">{{ 'PAGE.K8S.PACKAGEPATH' | translate }}:</span>
+                                <span class="value">{{ item?.package_path[0] }}</span>
+                            </p>
+                            <p class="label-value-pair">
+                                <span class="label">{{ 'MODIFIED' | translate }}:</span>
+                                <span class="value">{{ item.modified }}</span>
+                            </p>
+                        </div>
+                        <div class="card-footer">
+                            <div class="btn-group list" role="group">
+                                <button type="button" class="btn btn-primary" (click)='onView(item.identifier, 2)'
+                                    placement="top" container="body" ngbTooltip="{{'VIEW' | translate}}">
+                                    <i class="fa fa-eye"></i>
+                                </button>
+                            </div>
+                        </div>
+                    </div>
+                </ng-template>
+            </div>
+        </div>
+        <ng-template #noData>
+            <div class="no-data">
+                {{ 'NODATA' | translate }}
+            </div>
+        </ng-template>
+    </div>
+</div>
+<div id="demo" class="collapse context-style p-2" *ngIf="isCollapsed1 === true">
+    <div class="container">
+        <span class="button d-flex justify-content-end">
+            <button class="btn btn-primary mb-2 me-2" type="button" placement="top" container="body"
+                ngbTooltip="{{'Add Node' | translate}}" (click)="addK8sCluster('card_node')">
+                <i class="fas fa-plus-circle" aria-hidden="true"></i>&nbsp; {{ 'PAGE.K8S.ADDNODE' | translate}}
+            </button>
+        </span>
+        <div class="row info gx-3" *ngIf="node_count !== 0 else noData">
+            <div *ngFor="let item of nodeDetail" class="col-12 col-sm-4 col-md-4 col-lg-4 col-xl-4 mb-3">
+                <div class="custom-card card" style="width: 100%; max-width: 20rem;">
+                    <div class="card-header custom-card-header d-flex justify-content-between">
+                        <b style="font-size:medium;">{{ item.name }}</b>
+                        <span class="badge px-2" [ngClass]="{
+                      'bg-danger text-white': item.state === 'ERROR',
+                      'bg-success text-white': item.state === 'READY',
+                      'bg-warning text-white': ['IN_PROGRESS', 'IN_PROGRESS.GIT_SYNCED', 
+                                                'IN_PROGRESS.KUSTOMIZATION_READY', 
+                                                'IN_PROGRESS.KUSTOMIZATION_DELETED'].includes(item.state)}">
+                            {{ countData?.k8s_version }}
+                        </span>
+                        <span>
+                            <i *ngIf="item.state === 'READY'" class="fas fa-check-circle text-success"
+                                data-bs-toggle="tooltip" title="READY"></i>
+                            <i *ngIf="item.state.includes('IN_PROGRESS')" class="fas fa-spinner text-warning"
+                                data-bs-toggle="tooltip" [title]="item.state"></i>
+                            <i *ngIf="item.state === 'ERROR'" class="fas fa-times-circle text-danger"
+                                data-bs-toggle="tooltip" title="ERROR"></i>
+                        </span>
+                    </div>
+                    <div class="card-body">
+                        <p class="label-value-pair-description">
+                            <span class="label1">{{ 'PAGE.K8S.DESCRIPTION' | translate }}:</span>
+                            <span class="value1">
+                                <span class="short-description" (mouseenter)="showPopover($event, item.description)"
+                                    (mouseleave)="hidePopover()">
+                                    {{ item.description }}
+                                </span>
+                                <span class="popover-description" #popover
+                                    *ngIf="isPopoverVisible && item?.description.length > 15">{{ popoverText
+                                    }}</span>
+                            </span>
+                        </p>
+                        <hr>
+                        <p class="label-value-pair"><span class="label">{{ 'PAGE.K8S.NODESIZE' | translate }}:</span>
+                            <span class="value">{{
+                                item.nodeSize }}</span>
+                        </p>
+                        <p class="label-value-pair"><span class="label">{{ 'PAGE.K8S.NODECOUNT' | translate }}:</span>
+                            <span class="value">{{ item.nodeCount }}</span>
+                        </p>
+                        <p class="label-value-pair"><span class="label">{{ 'MODIFIED' | translate }}:</span> <span
+                                class="value">{{ item.modified }}</span></p>
+                    </div>
+                    <div class="card-footer">
+                        <div class="btn-group list" role="group">
+                            <button type="button" class="btn btn-primary" (click)='onView(item.identifier, 1)'
+                                placement="top" container="body" ngbTooltip="{{'VIEW' | translate}}">
+                                <i class="fa fa-eye"></i>
+                            </button>
+                            <button type="button" class="btn btn-primary" placement="top" container="body"
+                                ngbTooltip="{{'EDIT' | translate}}" [disabled]="item.state !== 'READY'"
+                                (click)='scaling(item.identifier, "edit-node")'>
+                                <i class="fas fa-edit"></i>
+                            </button>
+                            <button type="button" class="btn btn-primary" placement="top" container="body"
+                                ngbTooltip="{{'DELETE' | translate}}"
+                                [disabled]="item.state !== 'READY' && item.state !== 'ERROR'"
+                                (click)='onDelete(item.identifier, item.name, 1)'>
+                                <i class="far fa-trash-alt icons"></i>
+                            </button>
+                            <button type="button" class="btn btn-primary" placement="top" container="body"
+                                ngbTooltip="{{'PAGE.K8S.K8SSCALING' | translate}}" [disabled]="item.state !== 'READY'"
+                                (click)='scaling(item.identifier, "k8s-scale")'>
+                                <i class="fas fa-arrows-alt-v"></i>
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <ng-template #noData>
+            <div class="no-data">
+                {{ 'NODATA' | translate }}
+            </div>
+        </ng-template>
+    </div>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
diff --git a/src/app/k8s/k8s-info/K8sInfoComponent.scss b/src/app/k8s/k8s-info/K8sInfoComponent.scss
new file mode 100644 (file)
index 0000000..d3b10b6
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ 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: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+*/
+@import "../../../assets/scss/variable.scss";
+@import "../../../assets/scss/mixins/mixin.scss";
+
+.text-dark {
+   color: $gray-800;
+}
+
+.font-weight-bold {
+   font-weight: 700;
+}
+
+button.bg-light {
+   background-color: $gray-200;
+   &:hover,
+   &:focus {
+      background-color: $paleblue;
+   }
+}
+
+.btn-group {
+   display: flex;
+   &.list.action {
+      justify-content: center;
+      align-items: flex-start;
+      flex-wrap: wrap;
+      .btn {
+         border-top: 2px solid $primary;
+         transition:
+            transform 0.3s ease-in-out,
+            background-color 0.3s,
+            color 0.3s;
+         &.active {
+            background-color: $theme-bg-color;
+            font-weight: bold;
+            margin: 5px 0 0;
+            transform: scale(1);
+            .circle {
+               display: flex;
+               align-items: center;
+               justify-content: center;
+               width: 40px;
+               height: 40px;
+               border-radius: 50%;
+               background-color: $primary;
+               color: white;
+               position: absolute;
+               top: 0;
+               transform: translateY(-50%);
+            }
+            b {
+               font-size: 1.2em;
+            }
+            p {
+               font-size: 1em;
+            }
+         }
+         &:not(.active) {
+            transform: scale(0.97);
+            opacity: 0.8;
+            .circle {
+               display: flex;
+               align-items: center;
+               justify-content: center;
+               width: 40px;
+               height: 40px;
+               border-radius: 50%;
+               background-color: $gray-200;
+               color: black;
+               position: absolute;
+               top: 0;
+               transform: translateY(-50%);
+               border: 1px solid $primary;
+            }
+         }
+      }
+      .collapse {
+         transition:
+            background-color 0.3s,
+            color 0.3s;
+      }
+   }
+}
+.collapse {
+   display: flex;
+   flex-direction: column;
+   align-items: center;
+   justify-content: flex-start;
+   padding: 5px;
+   background-color: $theme-bg-color;
+}
+
+.btn p {
+   margin: 0;
+   padding-top: 20px;
+}
+
+.label-value-pair,
+.label-value-pair-description {
+   display: flex;
+   justify-content: space-between;
+   margin-bottom: 10px;
+   @include padding-value(3, 10, 0, 10);
+   align-items: center;
+   gap: 8px;
+   position: relative;
+}
+
+.label,
+.label1 {
+   font-weight: bold;
+   color: #343a40;
+   white-space: nowrap;
+}
+
+.value,
+.value1 {
+   display: -webkit-box;
+   -webkit-line-clamp: 2;
+   line-clamp: 2;
+   -webkit-box-orient: vertical;
+   overflow: hidden;
+   text-overflow: ellipsis;
+   cursor: pointer;
+   max-height: 3em;
+   line-height: 1.5em;
+   position: relative;
+   margin-left: 5px;
+   color: #343a40;
+   flex: 1;
+   min-width: 0;
+   overflow: visible;
+}
+
+.custom-card {
+   @include wh-value(null, 290px);
+   @include roundedCorners(5);
+   position: relative;
+   @include border(all, 1, solid, rgba(238, 238, 238, 0.75));
+   @include box-shadow(0px, 1px, 15px, 0px, rgba(69, 90, 100, 0.1));
+   background-color: $white;
+}
+
+.d-flex {
+   display: flex;
+   flex-wrap: nowrap;
+   align-items: center;
+   gap: 2px;
+   width: 100%;
+}
+
+.search-container {
+   position: relative;
+   width: 100%;
+   max-width: 300px;
+   height: 30px;
+   display: flex;
+}
+
+.search-input {
+   width: 100%;
+   padding-right: 40px;
+   box-sizing: border-box;
+   border: 1px solid $primary;
+}
+
+.search-icon {
+   position: absolute;
+   right: 10px;
+   top: 50%;
+   transform: translateY(-50%);
+   color: $primary;
+}
+
+.sort-dropdown {
+   display: flex;
+   align-items: center;
+   position: relative;
+   flex-shrink: 0;
+   min-width: 150px;
+   max-width: 200px;
+   margin-left: 2px;
+}
+
+#sort-icon {
+   margin-right: 10px;
+   cursor: pointer;
+}
+
+#sort-options {
+   padding: 2px;
+   cursor: pointer;
+}
+
+.custom-card-header {
+   background-color: $primary;
+   @include box-shadow(0px, 1px, 15px, 0px, rgba(69, 90, 100, 0.1));
+   @include roundedCorners(5);
+   color: white;
+}
+
+.version {
+   background-color: $secondary;
+   width: 40px;
+}
+
+.short-description {
+   display: -webkit-box;
+   -webkit-line-clamp: 2;
+   -webkit-box-orient: vertical;
+   overflow: hidden;
+   text-overflow: ellipsis;
+   cursor: pointer;
+   max-height: 3em;
+   line-height: 1.5em;
+   white-space: normal;
+   line-clamp: 2;
+}
+
+/* Tooltip Styling */
+.popover-description {
+   position: absolute;
+   background-color: $primary;
+   color: white;
+   padding: 8px;
+   border-radius: 5px;
+   font-size: 12px;
+   max-width: 300px;
+   white-space: normal;
+   display: none;
+   z-index: 1000;
+}
+
+.value1:hover .popover-description {
+   display: block;
+}
+
+.card-header,
+.card-footer {
+   padding: 12px;
+   font-weight: bold;
+}
+
+.card-body {
+   padding: 0;
+   margin: 0;
+   border-top: 1px solid #ddd;
+   border-bottom: 1px solid #ddd;
+}
+
+.no-data {
+   display: flex;
+   justify-content: center;
+   align-items: center;
+   padding: 20px 0;
+   text-align: center;
+   height: 260px;
+}
+
+::ng-deep .carousel-indicators {
+   display: none;
+}
+
+/* Hide default Bootstrap background images for arrows */
+::ng-deep .carousel-control-prev-icon,
+::ng-deep .carousel-control-next-icon {
+   background-image: none;
+   display: none;
+}
+
+/* Add Font Awesome icons for Previous & Next Arrows */
+::ng-deep .carousel-control-prev::before {
+   content: "\f104";
+   font-family: "Font Awesome 5 Free";
+   font-weight: 900;
+   width: 20px;
+   height: 20px;
+   position: relative;
+   color: white;
+   right: 22px;
+   bottom: 35px;
+   background-color: $primary;
+   border-radius: 50%;
+}
+
+::ng-deep .carousel-control-next::before {
+   content: "\f105";
+   font-family: "Font Awesome 5 Free";
+   font-weight: 900;
+   position: relative;
+   left: 22px;
+   bottom: 35px;
+   width: 20px;
+   height: 20px;
+   color: white;
+   background-color: $primary;
+   border-radius: 50%;
+}
diff --git a/src/app/k8s/k8s-info/K8sInfoComponent.ts b/src/app/k8s/k8s-info/K8sInfoComponent.ts
new file mode 100644 (file)
index 0000000..7a9d577
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ 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: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+*/
+/**
+ * @file Info K8s Page
+ */
+import { Component, HostListener, Injector, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { environment } from 'environment';
+import { K8SCLUSTERDATA, K8SCLUSTERDATADISPLAY, K8SNODEDATA } from 'K8sModel';
+import { KSUAddComponent } from 'KSUAddComponent';
+import { NodeAddComponent } from 'NodeAddComponent';
+import { RestService } from 'RestService';
+import { isNullOrUndefined, SharedService } from 'SharedService';
+import { ShowInfoComponent } from 'ShowInfoComponent';
+
+/**
+ * Creating component
+ * @Component K8sInfoComponent.html as template url
+ */
+@Component({
+  selector: 'app-info-k8s',
+  templateUrl: './K8sInfoComponent.html',
+  styleUrls: ['./K8sInfoComponent.scss']
+})
+/** Exporting a class @exports K8sInfoComponent */
+export class K8sInfoComponent implements OnInit {
+  /** To inject services @public */
+  public injector: Injector;
+
+  /** Contains active button @public */
+  public activeButton = 1;
+
+  /** condition to show tooltip @public */
+  public showTooltip = false;
+
+  /** Showing more details of collapase */
+  public isCollapsed1: boolean = true;
+
+  /** Showing more details of collapase */
+  public isCollapsed2: boolean = false;
+
+  /** Check the Projects loading results @public */
+  public isLoadingResults: boolean = false;
+
+  /** Give the message for the loading @public */
+  public message: string = 'PLEASEWAIT';
+
+  /** variables contains paramsID @public */
+  public paramsID: string;
+
+  /** Contains cluster name @public */
+  public clusterName: string;
+
+  /** Contains cluster data with count @public */
+  public countData: K8SCLUSTERDATA = {};
+
+  /** Contains node count @public */
+  public node_count: number;
+
+  /** Contains ksu count @public */
+  public ksu_count: number;
+
+  /** Contains node details @public */
+  public nodeDetail: {}[] = [];
+
+  /** Contains ksu details @public */
+  public ksuDetail: {}[] = [];
+
+  /** Condition for popover visibility @public */
+  public isPopoverVisible = false;
+
+  /** Contains popover text to show @public */
+  public popoverText = '';
+
+  /** Instance of the rest service @private */
+  private restService: RestService;
+
+  /** Holds teh instance of AuthService class of type AuthService @private */
+  private activatedRoute: ActivatedRoute;
+
+  /** Utilizes modal service for any modal operations @private */
+  private modalService: NgbModal;
+
+  /** Contains all methods related to shared @private */
+  private sharedService: SharedService;
+
+  constructor(injector: Injector) {
+    this.injector = injector;
+    this.restService = this.injector.get(RestService);
+    this.activatedRoute = this.injector.get(ActivatedRoute);
+    this.modalService = this.injector.get(NgbModal);
+    this.sharedService = this.injector.get(SharedService);
+  }
+
+  /**
+   * Lifecyle Hooks the trigger before component is instantiate
+   */
+  public ngOnInit(): void {
+    this.paramsID = this.activatedRoute.snapshot.paramMap.get('id');
+    this.generateData();
+  }
+
+  /** To view Details @public */
+  public onView(identifier: string, type: number): void {
+    let pageName: string = '';
+    let title: string = '';
+    if (type === 1) {
+      pageName = 'k8s-node';
+      title = 'Node Details';
+    } else {
+      pageName = 'k8s-ksu';
+      title = 'KSU Details';
+    }
+    // eslint-disable-next-line security/detect-non-literal-fs-filename
+    this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+      id: identifier,
+      page: pageName,
+      titleName: title,
+      cluster_id: this.paramsID
+    };
+  }
+
+  /** Edit Node @public */
+  public onEdit(type: number): void {
+    // eslint-disable-next-line security/detect-non-literal-fs-filename
+    const modalRef: NgbModalRef = this.modalService.open(NodeAddComponent, { backdrop: 'static' });
+    if (type === 1) {
+      modalRef.componentInstance.profileType = 'card-node';
+    }
+    modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+      if (result) {
+        this.sharedService.callData();
+      }
+    }).catch((): void => {
+      // Catch Navigation Error
+    });
+  }
+
+  /** Delete Operation @public */
+  public onDelete(id_value: string, name_value: string, type: number): void {
+    let pageName: string = '';
+    let title: string = '';
+    if (type === 1) {
+      pageName = 'card-node';
+      title = 'Node Details';
+    } else {
+      pageName = 'card-ksu';
+      title = 'KSU Details';
+    }
+    // eslint-disable-next-line security/detect-non-literal-fs-filename
+    const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+    modalRef.componentInstance.params = {
+      id: id_value,
+      page: pageName,
+      titleName: 'Node Details',
+      cluster_id: this.paramsID,
+      name: name_value
+    };
+    modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+      if (result) {
+        this.sharedService.callData();
+        this.nodeData();
+      }
+    }).catch((): void => {
+      // Catch Navigation Error
+    });
+  }
+
+  /** popover functionality to show full description @public */
+  public showPopover(event: MouseEvent, description: string) {
+    this.popoverText = description;
+    this.isPopoverVisible = true;
+    const popover = (event.target as HTMLElement).nextElementSibling as HTMLElement;
+    if (popover) {
+      // eslint-disable-next-line @typescript-eslint/no-magic-numbers
+      popover.style.top = `${event.clientY + 10}px`;
+      popover.style.left = `${event.clientX}px`;
+    }
+  }
+
+  /** To hide popover @public */
+  public hidePopover() {
+    this.isPopoverVisible = false;
+  }
+
+  /** Add Node/KSU @public */
+  public addK8sCluster(type?: string): void {
+    if (type === 'card_node') {
+      // eslint-disable-next-line security/detect-non-literal-fs-filename
+      const modalRef: NgbModalRef = this.modalService.open(NodeAddComponent, { backdrop: 'static' });
+      modalRef.componentInstance.profileType = type;
+      modalRef.componentInstance.clusterId = this.paramsID;
+      modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+        if (result) {
+          this.sharedService.callData();
+          this.nodeData();
+        }
+      }).catch((): void => {
+        // Catch Navigation Error
+      });
+    } else if (type === 'card_ksu') {
+      // eslint-disable-next-line security/detect-non-literal-fs-filename
+      const modalRef: NgbModalRef = this.modalService.open(KSUAddComponent, { backdrop: 'static' });
+      modalRef.componentInstance.profileType = 'card-add';
+      modalRef.componentInstance.profileID = this.paramsID;
+      modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+        if (result) {
+          this.sharedService.callData();
+          this.ksuData();
+        }
+      }).catch((): void => {
+        // Catch Navigation Error
+      });
+    }
+  }
+
+  /** Close tooltip when clicking outside @public */
+  @HostListener('document:click', ['$event'])
+  closeTooltip(event: Event) {
+    if (!(event.target as HTMLElement).classList.contains('short-description')) {
+      this.showTooltip = false;
+    }
+  }
+  /** Generate nodeData object from loop and return for the datasource @public */
+  public generateNodeData(nodedata: K8SCLUSTERDATA): K8SCLUSTERDATADISPLAY {
+    return {
+      name: nodedata.name,
+      state: !isNullOrUndefined(nodedata.resourceState) ? nodedata.resourceState : 'N/A',
+      identifier: nodedata._id,
+      version: nodedata.k8s_version,
+      description: !isNullOrUndefined(nodedata.description) ? nodedata.description : '-',
+      nodeCount: nodedata.node_count,
+      nodeSize: nodedata.node_size,
+      created: !isNullOrUndefined(nodedata?._admin?.created) ? this.sharedService.convertEpochTime(Number(nodedata._admin.created)) : '-',
+      modified: !isNullOrUndefined(nodedata?._admin?.modified) ? this.sharedService.convertEpochTime(Number(nodedata._admin.modified)) : '-'
+    };
+  }
+  /** Generate ksuData object from loop and return for the datasource @public */
+  public generateKsuData(ksudata: K8SCLUSTERDATA): K8SCLUSTERDATADISPLAY {
+    return {
+      name: ksudata.name,
+      state: !isNullOrUndefined(ksudata.resourceState) ? ksudata.resourceState : 'N/A',
+      identifier: ksudata._id,
+      version: ksudata.k8s_version,
+      description: !isNullOrUndefined(ksudata.description) ? ksudata.description : '-',
+      package_name: ksudata.package_name,
+      package_path: ksudata.package_path,
+      created: !isNullOrUndefined(ksudata?._admin?.created) ? this.sharedService.convertEpochTime(Number(ksudata._admin.created)) : '-',
+      modified: !isNullOrUndefined(ksudata?._admin?.modified) ? this.sharedService.convertEpochTime(Number(ksudata._admin.modified)) : '-'
+    };
+  }
+
+  /** Generate k8s Data function @public */
+  public generateData(): void {
+    this.isLoadingResults = true;
+    this.restService.getResource(environment.K8SCREATECLUSTER_URL + '/' + this.paramsID).subscribe((k8sClusterDatas: K8SCLUSTERDATA) => {
+      if (!isNullOrUndefined(k8sClusterDatas)) {
+        this.node_count = k8sClusterDatas.node_count;
+        this.ksu_count = k8sClusterDatas.ksu_count;
+        this.countData = k8sClusterDatas;
+        this.clusterName = k8sClusterDatas.name;
+        this.nodeData();
+      }
+      this.isLoadingResults = false;
+    }, (error: ERRORDATA) => {
+      this.restService.handleError(error, 'get');
+      this.isLoadingResults = false;
+    });
+  }
+
+  /** Generate node Data function @public */
+  public nodeData(): void {
+    this.isLoadingResults = true;
+    this.restService.getResource(environment.K8SCREATECLUSTER_URL + '/' + this.paramsID + '/nodegroup').subscribe((k8sClusterDatas: K8SCLUSTERDATA) => {
+      if (!isNullOrUndefined(k8sClusterDatas)) {
+        this.nodeDetail = [];
+        this.node_count = k8sClusterDatas.count;
+        k8sClusterDatas.data?.forEach((clusterData: K8SNODEDATA) => {
+          const k8sClusterDataObj: K8SCLUSTERDATADISPLAY = this.generateNodeData(clusterData);
+          this.nodeDetail.push(k8sClusterDataObj);
+        });
+      }
+      this.isLoadingResults = false;
+    }, (error: ERRORDATA) => {
+      this.restService.handleError(error, 'get');
+      this.isLoadingResults = false;
+    });
+  }
+
+  /** Generate ksu Data function @public */
+  public ksuData(): void {
+    this.isLoadingResults = true;
+    this.restService.getResource(environment.K8SCREATECLUSTER_URL + '/' + this.paramsID + '/ksus').subscribe((k8sClusterDatas: K8SCLUSTERDATA) => {
+      if (!isNullOrUndefined(k8sClusterDatas)) {
+        this.ksuDetail = [];
+        this.ksu_count = k8sClusterDatas.count;
+        k8sClusterDatas.data?.forEach((clusterData: K8SNODEDATA) => {
+          const k8sClusterDataObj: K8SCLUSTERDATADISPLAY = this.generateKsuData(clusterData);
+          this.ksuDetail.push(k8sClusterDataObj);
+        });
+      }
+      this.isLoadingResults = false;
+    }, (error: ERRORDATA) => {
+      this.restService.handleError(error, 'get');
+      this.isLoadingResults = false;
+    });
+  }
+
+  /** To capture active button @public */
+  public setActiveButton(buttonNumber: number) {
+    this.activeButton = buttonNumber;
+    if (buttonNumber === 1) {
+      this.nodeData();
+      this.isCollapsed1 = true;
+      this.isCollapsed2 = false;
+    } else if (buttonNumber === 2) {
+      this.ksuData();
+      this.isCollapsed2 = true;
+      this.isCollapsed1 = false;
+    }
+  }
+
+  /** Scaling @public */
+  public scaling(id: string, type?: string): void {
+    // eslint-disable-next-line security/detect-non-literal-fs-filename
+    const modalRef: NgbModalRef = this.modalService.open(NodeAddComponent, { backdrop: 'static' });
+    modalRef.componentInstance.clusterId = this.paramsID;
+    modalRef.componentInstance.profileID = id;
+    modalRef.componentInstance.profileType = type;
+    modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+      if (result) {
+        this.sharedService.callData();
+        this.nodeData();
+      }
+    }).catch((): void => {
+      // Catch Navigation Error
+    });
+  }
+
+  /** Edit KSU @public */
+  public editKsu(id?: string): void {
+    // eslint-disable-next-line security/detect-non-literal-fs-filename
+    const modalRef: NgbModalRef = this.modalService.open(KSUAddComponent, { backdrop: 'static' });
+    modalRef.componentInstance.profileID = id;
+    modalRef.componentInstance.profileType = 'edit';
+    modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+      if (result) {
+        this.sharedService.callData();
+        this.ksuData();
+      }
+    }).catch((): void => {
+      // Catch Navigation Error
+    });
+  }
+}
index e75cc7e..40154b1 100644 (file)
@@ -17,7 +17,7 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
 -->
 <form [formGroup]="KsuForm" (ngSubmit)="KSUAddSubmit();">
     <div class="modal-header">
-        <h4 *ngIf="profileType === 'add'" class="modal-title" id="modal-basic-title">{{'PAGE.K8S.ADDKSU' | translate}}</h4>
+        <h4 *ngIf="profileType === 'add'|| profileType === 'card-add'" class="modal-title" id="modal-basic-title">{{'PAGE.K8S.ADDKSU' | translate}}</h4>
         <h4 *ngIf="profileType === 'edit'"class="modal-title" id="modal-basic-title">{{'PAGE.K8S.EDITKSU' | translate}}</h4>
         <h4 *ngIf="profileType === 'move'"class="modal-title" id="modal-basic-title">{{'PAGE.K8S.MOVE' | translate}}</h4>
         <h4 *ngIf="profileType === 'clone'"class="modal-title" id="modal-basic-title">{{'PAGE.K8S.CLONE' | translate}}</h4>
@@ -99,7 +99,7 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
                                     <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
                                     <div class="custom-file">
                                         <input type="file" #fileInputConfig class="fileupload custom-file-input"
-                                            (change)="configFile($event.target.files)" id="customConfigFile">
+                                            (change)="configFile($event.target.files)" id="customConfigFile" [ngClass]="{ 'is-invalid': submitted && transformation.errors }">
                                     </div>
                                 </div>
                                 <div class="col-sm-1">
@@ -117,7 +117,7 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
     </div>
     <div class="modal-footer">
         <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
-        <button *ngIf="profileType === 'add'" type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+        <button *ngIf="profileType === 'add' || profileType === 'card-add'" type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
         <button *ngIf="profileType === 'edit'" type="submit" class="btn btn-primary">{{'Edit' | translate}}</button>
         <button *ngIf="profileType === 'move'" type="submit" class="btn btn-primary">{{'Move' | translate}}</button>
         <button *ngIf="profileType === 'clone'" type="submit" class="btn btn-primary">{{'Clone' | translate}}</button>
index 26f86f1..db13e4a 100644 (file)
@@ -167,6 +167,8 @@ export class KSUAddComponent implements OnInit {
         } else if (this.profileType === 'edit') {
             this.isKsu = true;
             this.getksuDetails();
+        } else if (this.profileType === 'card-add') {
+            this.isKsu = true;
         } else {
             this.isKsu = true;
         }
@@ -272,7 +274,7 @@ export class KSUAddComponent implements OnInit {
                     profile_type: this.KsuForm.value.profile_type
                 }
             };
-        } else if (this.profileType === 'edit' || this.profileType === 'add') {
+        } else if (this.profileType === 'edit' || this.profileType === 'add' || this.profileType === 'card-add') {
             this.addEditKSU();
         }
         this.submitted = true;
@@ -290,22 +292,24 @@ export class KSUAddComponent implements OnInit {
     /** Add/Edit KSU @public */
     public addEditKSU(): void {
         this.okaArray = this.KsuForm.get('oka') as FormArray;
-        const transValue = this.okaArray.at(0).get('transformation').value;
-        const validJSON: boolean = this.sharedService.checkJson(transValue);
-        if (validJSON) {
-            for (let i = 0; i < this.okaArray.length; i++) {
-                const formGroup = this.okaArray.at(i) as FormGroup;
-                formGroup.patchValue({
-                    transformation: JSON.parse(transValue)
-                });
-            }
-        } else {
-            const getConfigJson: string = jsyaml.load(transValue, { json: true });
-            for (let i = 0; i < this.okaArray.length; i++) {
-                const formGroup = this.okaArray.at(i) as FormGroup;
-                formGroup.patchValue({
-                    transformation: JSON.parse(getConfigJson)
-                });
+        const transValue = this.okaArray?.at(0)?.get('transformation').value;
+        if (!isNullOrUndefined(transValue)) {
+            const validJSON: boolean = this.sharedService.checkJson(transValue);
+            if (validJSON) {
+                for (let i = 0; i < this.okaArray.length; i++) {
+                    const formGroup = this.okaArray.at(i) as FormGroup;
+                    formGroup.patchValue({
+                        transformation: JSON.parse(transValue)
+                    });
+                }
+            } else {
+                const getConfigJson: string = jsyaml.load(transValue, { json: true });
+                for (let i = 0; i < this.okaArray.length; i++) {
+                    const formGroup = this.okaArray.at(i) as FormGroup;
+                    formGroup.patchValue({
+                        transformation: JSON.parse(getConfigJson)
+                    });
+                }
             }
         }
         if (this.profileType === 'edit') {
@@ -450,14 +454,27 @@ export class KSUAddComponent implements OnInit {
     /** Get profile details @public */
     public getprofileDetails(event: string, name?: string): void {
         this.profileData = [];
-        if (event === 'infra_config_profiles') {
-            this.profileUrl = environment.K8SINFRACONFIGPROFILE_URL;
-        } else if (event === 'infra_controller_profiles') {
-            this.profileUrl = environment.K8SINFRACONTROLLERPROFILE_URL;
-        } else if (event === 'app_profiles') {
-            this.profileUrl = environment.K8SAPPPROFILE_URL;
-        } else if (event === 'resource_profiles') {
-            this.profileUrl = environment.K8SRESOURCEPROFILE_URL;
+        if (this.profileType === 'card-add') {
+            if (event === 'infra_config_profiles') {
+                this.profileUrl = environment.K8SCREATECLUSTER_URL + '/' + this.profileID + '/' + event;
+            } else if (event === 'infra_controller_profiles') {
+                this.profileUrl = environment.K8SCREATECLUSTER_URL + '/' + this.profileID + '/' + event;
+            } else if (event === 'app_profiles') {
+                this.profileUrl = environment.K8SCREATECLUSTER_URL + '/' + this.profileID + '/' + event;
+            } else if (event === 'resource_profiles') {
+                this.profileUrl = environment.K8SCREATECLUSTER_URL + '/' + this.profileID + '/' + event;
+            }
+        }
+        else {
+            if (event === 'infra_config_profiles') {
+                this.profileUrl = environment.K8SINFRACONFIGPROFILE_URL;
+            } else if (event === 'infra_controller_profiles') {
+                this.profileUrl = environment.K8SINFRACONTROLLERPROFILE_URL;
+            } else if (event === 'app_profiles') {
+                this.profileUrl = environment.K8SAPPPROFILE_URL;
+            } else if (event === 'resource_profiles') {
+                this.profileUrl = environment.K8SRESOURCEPROFILE_URL;
+            }
         }
         this.restService.getResource(this.profileUrl)
             .subscribe((profileData: []): void => {
index de83ac5..493bfbe 100644 (file)
@@ -19,7 +19,7 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
   <div class="d-flex align-items-center header-style">{{'PAGE.K8S.KSU' | translate}}</div>
   <span class="button">
     <button class="btn btn-primary me-2" type="button" placement="top" container="body"
-      ngbTooltip="{{'Create Profile' | translate}}" (click)="addKSU()">
+      ngbTooltip="{{'PAGE.K8S.ADDKSU' | translate}}" (click)="addKSU()">
       <i class="fas fa-plus-circle" aria-hidden="true"></i>&nbsp; {{'PAGE.K8S.ADDKSU' | translate}}
     </button>
   </span>
@@ -28,10 +28,9 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
   <div class="col-auto me-auto">
     <nav class="custom-items-config">
       <span><i class="fas fa-clock text-success"></i>{{operationalStateFirstStep}}</span>
-      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateSecondStep}}</span>
-      <span><i class="fas fa-spinner text-danger"></i>{{operationalStateThirdStep}}</span>
-      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateFourthStep}}</span>
-      <span><i class="fas fa-times-circle text-warning"></i>{{operationalStateFifthStep}}</span>
+      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateSecondStep}}</span>
+      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateThirdStep}}</span>
+      <span><i class="fas fa-ban text-danger"></i>{{operationalStateFourthStep}}</span>
     </nav>
   </div>
   <page-per-row class="me-2" (pagePerRow)="onChange($event)"></page-per-row>
index 85a19d8..9339d9d 100644 (file)
@@ -69,9 +69,6 @@ export class KSUComponent implements OnInit, OnDestroy {
     /** operational State failed deletion data @public */
     public operationalStateFourthStep: string = CONFIGCONSTANT.k8OperationalStateFourthStep;
 
-    /** operational State failed creation data @public */
-    public operationalStateFifthStep: string = CONFIGCONSTANT.k8OperationalStateFifthStep;
-
     /** Check the loading results @public */
     public isLoadingResults: boolean = true;
 
@@ -121,7 +118,7 @@ export class KSUComponent implements OnInit, OnDestroy {
             name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
             identifier: { title: this.translateService.instant('IDENTIFIER'), width: '15%' },
             state: {
-                title: this.translateService.instant('GITSTATE'), width: '15%', type: 'html',
+                title: this.translateService.instant('STATE'), width: '15%', type: 'html',
                 filter: {
                     type: 'list',
                     config: {
@@ -130,34 +127,27 @@ export class KSUComponent implements OnInit, OnDestroy {
                             { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
                             { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
                             { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFifthStep }
+                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep }
                         ]
                     }
                 },
                 valuePrepareFunction: (cell: INFRACONFIGPAYLOAD, row: INFRACONFIGPAYLOAD): string => {
                     if (row.state === this.operationalStateFirstStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-clock text-success"></i>
-                                 </span>`;
+                                     <i class="fas fa-clock text-success"></i>
+                                     </span>`;
                     } else if (row.state === this.operationalStateSecondStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-warning"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateThirdStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-danger"></i>
-                                 </span>`;
+                                     <i class="fas fa-times-circle text-danger"></i>
+                                     </span>`;
                     } else if (row.state === this.operationalStateFourthStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-danger"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateFifthStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-warning"></i>
-                                 </span>`;
+                                     <i class="fas fa-ban text-danger"></i>
+                                     </span>`;
                     } else {
-                        return `<span>${row.state}</span>`;
+                        return `<span class="icon-label" title="${row.state}">
+                                     <i class="fas fa-spinner text-warning"></i>
+                                     </span>`;
                     }
                 }
             },
@@ -223,7 +213,7 @@ export class KSUComponent implements OnInit, OnDestroy {
             modified: this.sharedService.convertEpochTime(Number(ksudata._admin.modified)),
             description: ksudata.description,
             pageType: 'k8-ksu',
-            state: ksudata.state
+            state: ksudata.resourceState
         };
     }
 
index 34fb3fc..fa2ab9f 100644 (file)
@@ -28,10 +28,9 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
   <div class="col-auto me-auto">
     <nav class="custom-items-config">
       <span><i class="fas fa-clock text-success"></i>{{operationalStateFirstStep}}</span>
-      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateSecondStep}}</span>
-      <span><i class="fas fa-spinner text-danger"></i>{{operationalStateThirdStep}}</span>
-      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateFourthStep}}</span>
-      <span><i class="fas fa-times-circle text-warning"></i>{{operationalStateFifthStep}}</span>
+      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateSecondStep}}</span>
+      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateThirdStep}}</span>
+      <span><i class="fas fa-ban text-danger"></i>{{operationalStateFourthStep}}</span>
     </nav>
   </div>
   <page-per-row class="me-2" (pagePerRow)="onChange($event)"></page-per-row>
index 06cd6eb..fc48918 100644 (file)
@@ -69,9 +69,6 @@ export class K8sAppProfileComponent implements OnInit, OnDestroy {
     /** operational State failed deletion data @public */
     public operationalStateFourthStep: string = CONFIGCONSTANT.k8OperationalStateFourthStep;
 
-    /** operational State failed creation data @public */
-    public operationalStateFifthStep: string = CONFIGCONSTANT.k8OperationalStateFifthStep;
-
     /** Check the loading results @public */
     public isLoadingResults: boolean = true;
 
@@ -121,7 +118,7 @@ export class K8sAppProfileComponent implements OnInit, OnDestroy {
             name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
             identifier: { title: this.translateService.instant('IDENTIFIER'), width: '15%' },
             state: {
-                title: this.translateService.instant('GITSTATE'), width: '15%', type: 'html',
+                title: this.translateService.instant('STATE'), width: '15%', type: 'html',
                 filter: {
                     type: 'list',
                     config: {
@@ -130,34 +127,27 @@ export class K8sAppProfileComponent implements OnInit, OnDestroy {
                             { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
                             { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
                             { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFifthStep }
+                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep }
                         ]
                     }
                 },
                 valuePrepareFunction: (cell: INFRACONFIGPAYLOAD, row: INFRACONFIGPAYLOAD): string => {
                     if (row.state === this.operationalStateFirstStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-clock text-success"></i>
-                                 </span>`;
+                                   <i class="fas fa-clock text-success"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateSecondStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-warning"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateThirdStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-danger"></i>
-                                 </span>`;
+                                   <i class="fas fa-times-circle text-danger"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateFourthStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-danger"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateFifthStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-warning"></i>
-                                 </span>`;
+                                   <i class="fas fa-ban text-danger"></i>
+                                   </span>`;
                     } else {
-                        return `<span>${row.state}</span>`;
+                        return `<span class="icon-label" title="${row.state}">
+                                   <i class="fas fa-spinner text-warning"></i>
+                                   </span>`;
                     }
                 }
             },
@@ -223,7 +213,7 @@ export class K8sAppProfileComponent implements OnInit, OnDestroy {
             modified: this.sharedService.convertEpochTime(Number(profileData._admin.modified)),
             description: profileData.description,
             pageType: 'app-profile',
-            state: profileData.state
+            state: profileData.resourceState
         };
     }
 
index 81761d5..d96790d 100644 (file)
@@ -28,10 +28,9 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
   <div class="col-auto me-auto">
     <nav class="custom-items-config">
       <span><i class="fas fa-clock text-success"></i>{{operationalStateFirstStep}}</span>
-      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateSecondStep}}</span>
-      <span><i class="fas fa-spinner text-danger"></i>{{operationalStateThirdStep}}</span>
-      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateFourthStep}}</span>
-      <span><i class="fas fa-times-circle text-warning"></i>{{operationalStateFifthStep}}</span>
+      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateSecondStep}}</span>
+      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateThirdStep}}</span>
+      <span><i class="fas fa-ban text-danger"></i>{{operationalStateFourthStep}}</span>
     </nav>
   </div>
   <page-per-row class="me-2" (pagePerRow)="onChange($event)"></page-per-row>
index 2c76dbf..80ae4f6 100644 (file)
@@ -69,9 +69,6 @@ export class K8sInfraConfigProfileComponent implements OnInit, OnDestroy {
     /** operational State failed deletion data @public */
     public operationalStateFourthStep: string = CONFIGCONSTANT.k8OperationalStateFourthStep;
 
-    /** operational State failed creation data @public */
-    public operationalStateFifthStep: string = CONFIGCONSTANT.k8OperationalStateFifthStep;
-
     /** Check the loading results @public */
     public isLoadingResults: boolean = true;
 
@@ -121,7 +118,7 @@ export class K8sInfraConfigProfileComponent implements OnInit, OnDestroy {
             name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
             identifier: { title: this.translateService.instant('IDENTIFIER'), width: '15%' },
             state: {
-                title: this.translateService.instant('GITSTATE'), width: '15%', type: 'html',
+                title: this.translateService.instant('STATE'), width: '15%', type: 'html',
                 filter: {
                     type: 'list',
                     config: {
@@ -130,34 +127,27 @@ export class K8sInfraConfigProfileComponent implements OnInit, OnDestroy {
                             { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
                             { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
                             { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFifthStep }
+                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep }
                         ]
                     }
                 },
                 valuePrepareFunction: (cell: INFRACONFIGPAYLOAD, row: INFRACONFIGPAYLOAD): string => {
                     if (row.state === this.operationalStateFirstStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-clock text-success"></i>
-                                 </span>`;
+                                   <i class="fas fa-clock text-success"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateSecondStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-warning"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateThirdStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-danger"></i>
-                                 </span>`;
+                                   <i class="fas fa-times-circle text-danger"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateFourthStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-danger"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateFifthStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-warning"></i>
-                                 </span>`;
+                                   <i class="fas fa-ban text-danger"></i>
+                                   </span>`;
                     } else {
-                        return `<span>${row.state}</span>`;
+                        return `<span class="icon-label" title="${row.state}">
+                                   <i class="fas fa-spinner text-warning"></i>
+                                   </span>`;
                     }
                 }
             },
@@ -223,7 +213,7 @@ export class K8sInfraConfigProfileComponent implements OnInit, OnDestroy {
             modified: this.sharedService.convertEpochTime(Number(profileData._admin.modified)),
             description: profileData.description,
             pageType: 'infra-config',
-            state: profileData.state
+            state: profileData.resourceState
         };
     }
 
index 592a0cb..008c44f 100644 (file)
@@ -28,10 +28,9 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
   <div class="col-auto me-auto">
     <nav class="custom-items-config">
       <span><i class="fas fa-clock text-success"></i>{{operationalStateFirstStep}}</span>
-      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateSecondStep}}</span>
-      <span><i class="fas fa-spinner text-danger"></i>{{operationalStateThirdStep}}</span>
-      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateFourthStep}}</span>
-      <span><i class="fas fa-times-circle text-warning"></i>{{operationalStateFifthStep}}</span>
+      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateSecondStep}}</span>
+      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateThirdStep}}</span>
+      <span><i class="fas fa-ban text-danger"></i>{{operationalStateFourthStep}}</span>
     </nav>
   </div>
   <page-per-row class="me-2" (pagePerRow)="onChange($event)"></page-per-row>
index f5c93ae..ecb8165 100644 (file)
@@ -69,9 +69,6 @@ export class K8sInfraControllerProfileComponent implements OnInit, OnDestroy {
     /** operational State failed deletion data @public */
     public operationalStateFourthStep: string = CONFIGCONSTANT.k8OperationalStateFourthStep;
 
-    /** operational State failed creation data @public */
-    public operationalStateFifthStep: string = CONFIGCONSTANT.k8OperationalStateFifthStep;
-
     /** Check the loading results @public */
     public isLoadingResults: boolean = true;
 
@@ -121,7 +118,7 @@ export class K8sInfraControllerProfileComponent implements OnInit, OnDestroy {
             name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
             identifier: { title: this.translateService.instant('IDENTIFIER'), width: '15%' },
             state: {
-                title: this.translateService.instant('GITSTATE'), width: '15%', type: 'html',
+                title: this.translateService.instant('STATE'), width: '15%', type: 'html',
                 filter: {
                     type: 'list',
                     config: {
@@ -130,34 +127,27 @@ export class K8sInfraControllerProfileComponent implements OnInit, OnDestroy {
                             { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
                             { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
                             { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFifthStep }
+                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep }
                         ]
                     }
                 },
                 valuePrepareFunction: (cell: INFRACONFIGPAYLOAD, row: INFRACONFIGPAYLOAD): string => {
                     if (row.state === this.operationalStateFirstStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-clock text-success"></i>
-                                 </span>`;
+                                   <i class="fas fa-clock text-success"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateSecondStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-warning"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateThirdStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-danger"></i>
-                                 </span>`;
+                                   <i class="fas fa-times-circle text-danger"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateFourthStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-danger"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateFifthStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-warning"></i>
-                                 </span>`;
+                                   <i class="fas fa-ban text-danger"></i>
+                                   </span>`;
                     } else {
-                        return `<span>${row.state}</span>`;
+                        return `<span class="icon-label" title="${row.state}">
+                                   <i class="fas fa-spinner text-warning"></i>
+                                   </span>`;
                     }
                 }
             },
@@ -222,7 +212,7 @@ export class K8sInfraControllerProfileComponent implements OnInit, OnDestroy {
             modified: this.sharedService.convertEpochTime(Number(profileData._admin.modified)),
             description: profileData.description,
             pageType: 'infra-controller',
-            state: profileData.state
+            state: profileData.resourceState
         };
     }
 
index 2e76c13..1290c56 100644 (file)
@@ -28,10 +28,9 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
   <div class="col-auto me-auto">
     <nav class="custom-items-config">
       <span><i class="fas fa-clock text-success"></i>{{operationalStateFirstStep}}</span>
-      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateSecondStep}}</span>
-      <span><i class="fas fa-spinner text-danger"></i>{{operationalStateThirdStep}}</span>
-      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateFourthStep}}</span>
-      <span><i class="fas fa-times-circle text-warning"></i>{{operationalStateFifthStep}}</span>
+      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateSecondStep}}</span>
+      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateThirdStep}}</span>
+      <span><i class="fas fa-ban text-danger"></i>{{operationalStateFourthStep}}</span>
     </nav>
   </div>
   <page-per-row class="me-2" (pagePerRow)="onChange($event)"></page-per-row>
index b1dbf95..aa3d6e4 100644 (file)
@@ -69,9 +69,6 @@ export class K8sResourceProfileComponent implements OnInit, OnDestroy {
     /** operational State failed deletion data @public */
     public operationalStateFourthStep: string = CONFIGCONSTANT.k8OperationalStateFourthStep;
 
-    /** operational State failed creation data @public */
-    public operationalStateFifthStep: string = CONFIGCONSTANT.k8OperationalStateFifthStep;
-
     /** Check the loading results @public */
     public isLoadingResults: boolean = true;
 
@@ -121,7 +118,7 @@ export class K8sResourceProfileComponent implements OnInit, OnDestroy {
             name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
             identifier: { title: this.translateService.instant('IDENTIFIER'), width: '15%' },
             state: {
-                title: this.translateService.instant('GITSTATE'), width: '15%', type: 'html',
+                title: this.translateService.instant('STATE'), width: '15%', type: 'html',
                 filter: {
                     type: 'list',
                     config: {
@@ -130,34 +127,27 @@ export class K8sResourceProfileComponent implements OnInit, OnDestroy {
                             { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
                             { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
                             { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFifthStep }
+                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep }
                         ]
                     }
                 },
                 valuePrepareFunction: (cell: INFRACONFIGPAYLOAD, row: INFRACONFIGPAYLOAD): string => {
                     if (row.state === this.operationalStateFirstStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-clock text-success"></i>
-                                 </span>`;
+                                   <i class="fas fa-clock text-success"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateSecondStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-warning"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateThirdStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-danger"></i>
-                                 </span>`;
+                                   <i class="fas fa-times-circle text-danger"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateFourthStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-danger"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateFifthStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-warning"></i>
-                                 </span>`;
+                                   <i class="fas fa-ban text-danger"></i>
+                                   </span>`;
                     } else {
-                        return `<span>${row.state}</span>`;
+                        return `<span class="icon-label" title="${row.state}">
+                                   <i class="fas fa-spinner text-warning"></i>
+                                   </span>`;
                     }
                 }
             },
@@ -223,7 +213,7 @@ export class K8sResourceProfileComponent implements OnInit, OnDestroy {
             modified: this.sharedService.convertEpochTime(Number(profileData._admin.modified)),
             description: profileData.description,
             pageType: 'resource-profile',
-            state: profileData.state
+            state: profileData.resourceState
         };
     }
 
index 3c01f4f..c523022 100644 (file)
@@ -31,15 +31,15 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
 </div>
 <div class="mt-2 mb-2 list-utilites-actions">
   <div class="col-auto me-auto">
-    <nav class="custom-items-config">
+    <nav class="custom-items-config mt-2 mb-2">
       <span><i class="fas fa-cloud-upload-alt text-info"></i>{{clusterModeFirstStep}}</span>
       <span><i class="fas fa-clipboard-check text-info"></i>{{clusterModeSecondStep}}</span>
       <span><i class="fas fa-clock text-success"></i>{{operationalStateFirstStep}}</span>
-      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateSecondStep}}</span>
-      <span><i class="fas fa-spinner text-danger"></i>{{operationalStateThirdStep}}</span>
-      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateFourthStep}}</span>
-      <span><i class="fas fa-times-circle text-warning"></i>{{operationalStateFifthStep}}</span>
-      <span><i class="fas fa-ban text-danger"></i>{{operationalStateSixthStep}}</span>
+      <span><i class="fas fa-check-circle text-success"></i>{{operationalStateFifthStep}}</span>
+      <span><i class="fas fa-spinner text-warning"></i>{{operationalStateThirdStep}}</span>
+      <span><i class="fas fa-arrow-circle-down text-warning"></i>{{operationalStateSixthStep}}</span>
+      <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateSecondStep}}</span>
+      <span><i class="fas fa-ban text-danger"></i>{{operationalStateFourthStep}}</span>
     </nav>
   </div>
   <page-per-row class="me-2" (pagePerRow)="onChange($event)"></page-per-row>
index c79493e..c50831c 100644 (file)
@@ -76,7 +76,7 @@ export class K8sClusterComponent implements OnInit, OnDestroy {
   /** operational State in deletion data @public */
   public operationalStateThirdStep: string = CONFIGCONSTANT.k8OperationalStateThirdStep;
 
-  /** operational State failed deletion data @public */
+  /** operational State failed creation data @public */
   public operationalStateFourthStep: string = CONFIGCONSTANT.k8OperationalStateFourthStep;
 
   /** operational State failed creation data @public */
@@ -165,7 +165,7 @@ export class K8sClusterComponent implements OnInit, OnDestroy {
         }
       },
       state: {
-        title: this.translateService.instant('GITSTATE'), width: '15%', type: 'html',
+        title: this.translateService.instant('STATE'), width: '15%', type: 'html',
         filter: {
           type: 'list',
           config: {
@@ -176,7 +176,7 @@ export class K8sClusterComponent implements OnInit, OnDestroy {
               { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep },
               { value: this.operationalStateFourthStep, title: this.operationalStateFourthStep },
               { value: this.operationalStateFifthStep, title: this.operationalStateFifthStep },
-              { value: this.operationalStateSixthStep, title: this.operationalStateFifthStep }
+              { value: this.operationalStateSixthStep, title: this.operationalStateSixthStep }
             ]
           }
         },
@@ -187,30 +187,27 @@ export class K8sClusterComponent implements OnInit, OnDestroy {
                          </span>`;
           } else if (row.state === this.operationalStateSecondStep) {
             return `<span class="icon-label" title="${row.state}">
-                         <i class="fas fa-spinner text-warning"></i>
-                         </span>`;
-          } else if (row.state === this.operationalStateThirdStep) {
-            return `<span class="icon-label" title="${row.state}">
-                         <i class="fas fa-spinner text-danger"></i>
+                         <i class="fas fa-times-circle text-danger"></i>
                          </span>`;
           } else if (row.state === this.operationalStateFourthStep) {
             return `<span class="icon-label" title="${row.state}">
-                         <i class="fas fa-times-circle text-danger"></i>
+                         <i class="fas fa-ban text-danger"></i>
                          </span>`;
           } else if (row.state === this.operationalStateFifthStep) {
             return `<span class="icon-label" title="${row.state}">
-                         <i class="fas fa-times-circle text-warning"></i>
+                         <i class="fas fa-check-circle text-success"></i>
                          </span>`;
           } else if (row.state === this.operationalStateSixthStep) {
             return `<span class="icon-label" title="${row.state}">
-                         <i class="fas fa-ban text-danger"></i>
+                         <i class="fas fa-arrow-circle-down text-warning"></i>
                          </span>`;
           } else {
-            return `<span>${row.state}</span>`;
+            return `<span class="icon-label" title="${row.state}">
+                         <i class="fas fa-spinner text-warning"></i>
+                         </span>`;
           }
         }
       },
-      created: { title: this.translateService.instant('CREATED'), width: '15%' },
       Actions: {
         name: 'Action', width: '5%', filter: false, sort: false, title: this.translateService.instant('ACTIONS'), type: 'custom',
         valuePrepareFunction: (cell: K8SCLUSTERDATADISPLAY, row: K8SCLUSTERDATADISPLAY): K8SCLUSTERDATADISPLAY => row,
@@ -248,8 +245,10 @@ export class K8sClusterComponent implements OnInit, OnDestroy {
 
     if (type === 'Register') {
       modalRef.componentInstance.profileType = 'Register';
-    } else {
+    } else if (type === 'Manage') {
       modalRef.componentInstance.profileType = 'Manage';
+    } else {
+      modalRef.componentInstance.profileType = 'Control';
     }
     modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
       if (result) {
@@ -271,9 +270,8 @@ export class K8sClusterComponent implements OnInit, OnDestroy {
   public generateK8sclusterData(k8sClusterdata: K8SCLUSTERDATA): K8SCLUSTERDATADISPLAY {
     return {
       name: k8sClusterdata.name,
-      state: !isNullOrUndefined(k8sClusterdata.state) ? k8sClusterdata.state : 'N/A',
+      state: !isNullOrUndefined(k8sClusterdata.resourceState) ? k8sClusterdata.resourceState : 'N/A',
       identifier: k8sClusterdata._id,
-      operationalState: !isNullOrUndefined(k8sClusterdata._admin.operationalState) ? k8sClusterdata._admin.operationalState : 'N/A',
       version: k8sClusterdata.k8s_version,
       created: this.sharedService.convertEpochTime(Number(k8sClusterdata._admin.created)),
       modified: this.sharedService.convertEpochTime(Number(k8sClusterdata._admin.modified)),
@@ -281,7 +279,7 @@ export class K8sClusterComponent implements OnInit, OnDestroy {
       createdbyosm: !isNullOrUndefined(k8sClusterdata.created) ? (k8sClusterdata.created) : 'false',
       bootstrap: !isNullOrUndefined(k8sClusterdata.bootstrap) ? (k8sClusterdata.bootstrap) : false,
       key: (k8sClusterdata.key === 'registered') ? true : false,
-      clusterMode: (k8sClusterdata.created === 'true') ? 'MANAGED' : 'REGISTERED'
+      clusterMode: (k8sClusterdata.created === 'true') ? 'managed' : 'registered'
     };
   }
 
diff --git a/src/app/k8s/node-add/NodeAddComponent.html b/src/app/k8s/node-add/NodeAddComponent.html
new file mode 100644 (file)
index 0000000..5c44524
--- /dev/null
@@ -0,0 +1,126 @@
+<!--
+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: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+-->
+<form [formGroup]="nodeForm" (ngSubmit)="nodeSubmit();" (keydown.enter)="$event.preventDefault()">
+  <div class="modal-header">
+    <h4 *ngIf="profileType === 'card_node'" class="modal-title" id="modal-basic-title">
+      {{'PAGE.K8S.CREATENODEGROUP' |
+      translate}}
+    </h4>
+    <h4 *ngIf="profileType === 'edit-node'" class="modal-title" id="modal-basic-title">{{'PAGE.K8S.EDITNODE' |
+      translate}}
+    </h4>
+    <h4 *ngIf="profileType === 'k8s-scale'" class="modal-title" id="modal-basic-title">{{'PAGE.K8S.K8SSCALING' |
+      translate}}
+    </h4>
+    <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+      <i class="fas fa-times-circle text-danger"></i>
+    </button>
+  </div>
+  <div class="modal-body modal-body-custom-height">
+    <div class="form-group row mb-3" *ngIf="profileType === 'card_node'">
+      <label class="col-sm-12 col-form-label mandatory-label"
+        [ngClass]="{'text-danger': nodeForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' |
+        translate}}</label>
+      <label class="col-sm-4 col-form-label" for="name">{{'PAGE.K8S.NAME' | translate}}*</label>
+      <div class="col-sm-8">
+        <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.NAME' | translate}}" type="text"
+          formControlName="name" id="name" [ngClass]="{ 'is-invalid': submitted && f.name.errors }" required>
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf="profileType === 'edit-node'">
+      <label class="col-sm-4 col-form-label" for="name">{{'PAGE.K8S.NAME' | translate}}</label>
+      <div class="col-sm-8">
+        <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.NAME' | translate}}" type="text"
+          formControlName="edit_name" id="name" [ngClass]="{ 'is-invalid': submitted && f.edit_name.errors }">
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf="profileType === 'card_node' || profileType === 'edit-node'">
+      <label class="col-sm-4 col-form-label" for="description">{{'PAGE.K8S.DESCRIPTION' | translate}}</label>
+      <div class="col-sm-8">
+        <textarea class="form-control" placeholder="{{'PAGE.K8S.DESCRIPTION' | translate}}" type="text"
+          formControlName="description" id="description"
+          [ngClass]="{ 'is-invalid': submitted && f.description.errors }"></textarea>
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf="profileType === 'card_node'">
+      <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.NODESIZE' | translate}}*</label>
+      <div class="col-sm-8">
+        <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.NODESIZE' | translate}}" type="text"
+          formControlName="node_size" id="node_size" [ngClass]="{ 'is-invalid': submitted && f.node_size.errors }"
+          required>
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf="profileType === 'card_node'">
+      <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.NODECOUNT' | translate}}*</label>
+      <div class="col-sm-8">
+        <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.NODECOUNT' | translate}}" type="text"
+          formControlName="node_count" id="node_count" [ngClass]="{ 'is-invalid': submitted && f.node_count.errors }"
+          required>
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf="profileType === 'k8s-scale'">
+      <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.NODECOUNT' | translate}}</label>
+      <div class="col-sm-8">
+        <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.NODECOUNT' | translate}}" type="text"
+          formControlName="nodeCount" id="node_count" [ngClass]="{ 'is-invalid': submitted && f.node_count.errors }">
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf="profileType === 'card_node'">
+      <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.NODEROLE' | translate}}</label>
+      <div class="col-sm-8">
+        <input autocomplete="off" class="form-control" placeholder="{{'arn:aws:iam::[account-id]:role/[role-name]' | translate}}" type="text"
+          formControlName="role" id="role" [ngClass]="{ 'is-invalid': submitted && f.role.errors }">
+      </div>
+    </div>
+    <div class="card bg-light" *ngIf="profileType === 'card_node'">
+      <div class="card-body">
+        <div class="form-group row mb-3">
+          <label class="col-sm-4 col-form-label fw-semibold" for="k8s_version">{{'PAGE.K8S.SUBNET' | translate}}*</label>
+        </div>
+        <div class="form-group row mb-3">
+          <label class="col-sm-4 col-form-label" for="subnets_id">{{ 'PAGE.K8S.PRIVATESUBNET' | translate }}</label>
+          <div class="col-sm-8">
+            <ng-select placeholder="{{'SELECT' | translate}} {{'PAGE.K8S.PRIVATESUBNET' | translate}}"
+              [items]="privatesubnetItems" bindLabel="id" bindValue="id" [multiple]="true" id="private_subnet"
+              formControlName="private_subnet" [ngClass]="{ 'is-invalid': submitted && f.private_subnet.errors }"
+              [(ngModel)]="privateItems">
+            </ng-select>
+          </div>
+        </div>
+        <div class="form-group row mb-3">
+          <label class="col-sm-4 col-form-label" for="subnets_id">{{ 'PAGE.K8S.PUBLICSUBNET' | translate }}</label>
+          <div class="col-sm-8">
+            <ng-select placeholder="{{'SELECT' | translate}} {{'PAGE.K8S.PUBLICSUBNET' | translate}}"
+              [items]="publicsubnetItems" bindLabel="id" bindValue="id" [multiple]="true" id="public_subnet"
+              formControlName="public_subnet" [ngClass]="{ 'is-invalid': submitted && f.public_subnet.errors }"
+              [(ngModel)]="publicItems">
+            </ng-select>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+    <button *ngIf="profileType === 'card_node'" type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+    <button *ngIf="profileType === 'k8s-scale' || profileType === 'edit-node'" type="submit"
+      class="btn btn-primary">{{'APPLY'
+      | translate}}</button>
+  </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
diff --git a/src/app/k8s/node-add/NodeAddComponent.scss b/src/app/k8s/node-add/NodeAddComponent.scss
new file mode 100644 (file)
index 0000000..c55461a
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ 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: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+*/
\ No newline at end of file
diff --git a/src/app/k8s/node-add/NodeAddComponent.ts b/src/app/k8s/node-add/NodeAddComponent.ts
new file mode 100644 (file)
index 0000000..604a869
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ 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: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+*/
+/**
+ * @file K8sAddClusterComponent.ts.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { AbstractControl, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA, TYPESECTION } from 'CommonModel';
+import { environment } from 'environment';
+import { K8SCLUSTERDATA, K8SPayload } from 'K8sModel';
+import { RestService } from 'RestService';
+import { isNullOrUndefined, SharedService } from 'SharedService';
+/**
+ * Creating Component
+ * @Component takes NodeAddComponent.html as template url
+ */
+@Component({
+    selector: 'app-node-add',
+    templateUrl: './NodeAddComponent.html',
+    styleUrls: ['./NodeAddComponent.scss']
+})
+/** Exporting a class @exports NodeAddComponent */
+export class NodeAddComponent implements OnInit {
+    /** To inject services @public */
+    public injector: Injector;
+
+    /** FormGroup instance added to the form @ html @public */
+    public nodeForm: FormGroup;
+
+    /** Contains all vim account collections */
+    public clusterItems: K8SCLUSTERDATA;
+
+    /** Input contains Modal dialog component Instance @public */
+    @Input() public profileType: string;
+
+    /** Input contains Modal dialog component Instance @public */
+    @Input() public profileID: string;
+
+    /** Input contains Modal dialog component Instance @public */
+    @Input() public clusterId: string;
+
+    /** Instance for active modal service @public */
+    public activeModal: NgbActiveModal;
+
+    /** Variable set for twoway bindng @public  */
+    public vimAccountId: string;
+
+    /** contains url @public  */
+    public clusterUrl: string;
+
+    /** contains privatesubnet items @public  */
+    privateItems: [] = [];
+
+    /** contains publicsubnet items @public  */
+    publicItems: [] = [];
+
+    /** contains privatesubnet items from api @public  */
+    privatesubnetItems: {};
+
+    /** contains publicsubnet itams from api @public  */
+    publicsubnetItems: {};
+
+    /** contains cluster ID @public  */
+    public cluster_name: string;
+
+    /** contains scaling action paylaod@public  */
+    public scalingPayload = {};
+
+    /** Form submission Add */
+    public submitted: boolean = false;
+
+    /** contains payload */
+    public payload: K8SPayload;
+
+    /** Check the loading results @public */
+    public isLoadingResults: boolean = false;
+
+    /** Give the message for the loading @public */
+    public message: string = 'PLEASEWAIT';
+
+    /** FormBuilder instance added to the formBuilder @private */
+    private formBuilder: FormBuilder;
+
+    /** Utilizes rest service for any CRUD operations @private */
+    private restService: RestService;
+
+    /** Notifier service to popup notification @private */
+    private notifierService: NotifierService;
+
+    /** Contains tranlsate instance @private */
+    private translateService: TranslateService;
+
+    /** Controls the header form @private */
+    private headers: HttpHeaders;
+
+    /** Contains all methods related to shared @private */
+    private sharedService: SharedService;
+
+    constructor(injector: Injector) {
+        this.injector = injector;
+        this.restService = this.injector.get(RestService);
+        this.activeModal = this.injector.get(NgbActiveModal);
+        this.formBuilder = this.injector.get(FormBuilder);
+        this.notifierService = this.injector.get(NotifierService);
+        this.translateService = this.injector.get(TranslateService);
+        this.sharedService = this.injector.get(SharedService);
+    }
+
+    public ngOnInit(): void {
+        /** On Initializing call the methods */
+        this.nodeFormAction();
+        this.getDetailsvimAccount();
+        this.headers = new HttpHeaders({
+            Accept: 'application/json',
+            'Content-Type': 'application/json',
+            'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+        });
+        if (this.profileType === 'card_node') {
+            this.cluster_name = this.clusterId;
+            this.clusterChange();
+        } else if (this.profileType === 'k8s-scale' || this.profileType === 'edit-node') {
+            this.cluster_name = this.clusterId;
+            this.getDetails();
+        }
+        else {
+            this.cluster_name = null;
+        }
+    }
+
+    /** On modal initializing forms  @public */
+    public nodeFormAction(): void {
+        this.nodeForm = this.formBuilder.group({
+            name: ['', [Validators.required]],
+            description: [''],
+            node_count: ['', [Validators.required]],
+            node_size: ['', [Validators.required]],
+            nodeCount: [''],
+            role: [''],
+            public_subnet: [[]],
+            private_subnet: [[]],
+            cluster_id: ['', [Validators.required]],
+            edit_name: ['']
+        });
+    }
+
+    /** convenience getter for easy access to form fields */
+    get f(): FormGroup['controls'] { return this.nodeForm.controls; }
+
+
+    /** Call the vimAccount details in the selection options @public */
+    public getDetailsvimAccount(): void {
+        this.isLoadingResults = true;
+        this.restService.getResource(environment.K8SCREATECLUSTER_URL).subscribe((vimAccounts: K8SCLUSTERDATA) => {
+            this.clusterItems = vimAccounts;
+            this.isLoadingResults = false;
+        }, (error: ERRORDATA) => {
+            this.restService.handleError(error, 'get');
+            this.isLoadingResults = false;
+        });
+    }
+
+    /** To patch value for edit @public */
+    public getDetails(): void {
+        this.isLoadingResults = true;
+        this.restService.getResource(environment.K8SCREATECLUSTER_URL + '/' + this.cluster_name + '/nodegroup' + '/' + this.profileID).subscribe((vimAccounts: K8SCLUSTERDATA) => {
+            if (this.profileType === 'edit-node') {
+                this.nodeForm.patchValue({ edit_name: vimAccounts.name, description: vimAccounts.description });
+            } else if (this.profileType === 'k8s-scale') {
+                this.nodeForm.patchValue({ nodeCount: vimAccounts.node_count });
+            }
+            this.isLoadingResults = false;
+        }, (error: ERRORDATA) => {
+            this.restService.handleError(error, 'get');
+            this.isLoadingResults = false;
+        });
+    }
+
+    /** To get privatesubnet and publicsubnet details @public */
+    public clusterChange(): void {
+        this.isLoadingResults = true;
+        this.restService.getResource(environment.K8SCREATECLUSTER_URL + '/' + this.cluster_name).subscribe((vimAccounts: K8SCLUSTERDATA) => {
+            if (!isNullOrUndefined(vimAccounts)) {
+                this.privatesubnetItems = vimAccounts.private_subnet;
+                this.publicsubnetItems = vimAccounts.public_subnet;
+            }
+            this.isLoadingResults = false;
+        }, (error: ERRORDATA) => {
+            this.restService.handleError(error, 'get');
+            this.isLoadingResults = false;
+        });
+    }
+
+    /** On modal submit nodeSubmit will called @public */
+    public nodeSubmit(): void {
+        if (this.profileType === 'card_node') {
+            this.getFormControl('nodeCount').disable();
+            this.getFormControl('cluster_id').disable();
+            this.getFormControl('edit_name').disable();
+            this.clusterUrl = environment.K8SCREATECLUSTER_URL + '/' + this.cluster_name + '/nodegroup';
+            this.createNode();
+        } else if (this.profileType === 'k8s-scale') {
+            this.getFormControl('cluster_id').disable();
+            this.getFormControl('name').disable();
+            this.getFormControl('description').disable();
+            this.getFormControl('private_subnet').disable();
+            this.getFormControl('public_subnet').disable();
+            this.getFormControl('role').disable();
+            this.getFormControl('node_count').disable();
+            this.getFormControl('node_size').disable();
+            this.getFormControl('edit_name').disable();
+            this.clusterUrl = environment.K8SCREATECLUSTER_URL + '/' + this.cluster_name + '/nodegroup' + '/' + this.profileID + '/scale';
+            this.scaling();
+        } else if (this.profileType === 'edit-node') {
+            this.getFormControl('cluster_id').disable();
+            this.getFormControl('nodeCount').disable();
+            this.getFormControl('private_subnet').disable();
+            this.getFormControl('public_subnet').disable();
+            this.getFormControl('role').disable();
+            this.getFormControl('node_count').disable();
+            this.getFormControl('node_size').disable();
+            this.getFormControl('name').disable();
+            this.clusterUrl = environment.K8SCREATECLUSTER_URL + '/' + this.cluster_name + '/nodegroup' + '/' + this.profileID;
+            this.update();
+        }
+    }
+
+    /** Create Node @public */
+    public createNode(): void {
+        this.submitted = true;
+        this.sharedService.cleanForm(this.nodeForm);
+        if (this.nodeForm.invalid) {
+            return;
+        }
+        const modalData: MODALCLOSERESPONSEDATA = {
+            message: 'Done'
+        };
+        const apiURLHeader: APIURLHEADER = {
+            url: this.clusterUrl,
+            httpOptions: { headers: this.headers }
+        };
+        this.isLoadingResults = true;
+        const formData = this.nodeForm.value;
+        const payload = Object.keys(formData).reduce((acc, key) => {
+            const value = formData[key];
+            if (key === 'node_count' && value !== null && value !== undefined && value !== '') {
+                acc[key] = Number(value);
+            } else if (value !== null && value !== undefined && value !== '' && value.length !== 0) {
+                acc[key] = value;
+            }
+            return acc;
+        }, {});
+        this.restService.postResource(apiURLHeader, payload).subscribe((result: {}) => {
+            this.activeModal.close(modalData);
+            this.isLoadingResults = false;
+            this.notifierService.notify('success', this.nodeForm.value.name +
+                this.translateService.instant('PAGE.K8S.NODECREATEDSUCCESSFULLY'));
+        }, (error: ERRORDATA) => {
+            this.restService.handleError(error, 'post');
+            this.isLoadingResults = false;
+        });
+    }
+    /** Node Scaling @public */
+    public scaling(): void {
+        this.submitted = true;
+        this.sharedService.cleanForm(this.nodeForm);
+        if (this.nodeForm.invalid) {
+            return;
+        }
+        const modalData: MODALCLOSERESPONSEDATA = {
+            message: 'Done'
+        };
+        const apiURLHeader: APIURLHEADER = {
+            url: this.clusterUrl,
+            httpOptions: { headers: this.headers }
+        };
+        this.isLoadingResults = true;
+        if (this.profileType === 'k8s-scale') {
+            this.scalingPayload = {
+                node_count: Number(this.nodeForm.value.nodeCount)
+            };
+        }
+        this.restService.postResource(apiURLHeader, this.scalingPayload).subscribe((result: {}) => {
+            this.activeModal.close(modalData);
+            this.isLoadingResults = false;
+            this.notifierService.notify('success',
+                this.translateService.instant('PAGE.K8S.NODEUPDATEDSUCCESSFULLY'));
+        }, (error: ERRORDATA) => {
+            this.restService.handleError(error, 'post');
+            this.isLoadingResults = false;
+        });
+    }
+    /** Node update @public */
+    public update(): void {
+        this.submitted = true;
+        this.sharedService.cleanForm(this.nodeForm);
+        if (this.nodeForm.invalid) {
+            return;
+        }
+        const modalData: MODALCLOSERESPONSEDATA = {
+            message: 'Done'
+        };
+        const apiURLHeader: APIURLHEADER = {
+            url: this.clusterUrl,
+            httpOptions: { headers: this.headers }
+        };
+        this.isLoadingResults = true;
+        if (this.profileType === 'edit-node') {
+            if (this.nodeForm.value.description === '') {
+                this.scalingPayload = {
+                    name: this.nodeForm.value.edit_name
+                };
+                delete this.nodeForm.value.description;
+            } else if (this.nodeForm.value.name === '') {
+                this.scalingPayload = {
+                    description: this.nodeForm.value.description
+                };
+                delete this.nodeForm.value.name;
+            } else {
+                this.scalingPayload = {
+                    name: this.nodeForm.value.edit_name,
+                    description: this.nodeForm.value.description
+                };
+            }
+        }
+        this.restService.patchResource(apiURLHeader, this.scalingPayload).subscribe((result: {}) => {
+            this.activeModal.close(modalData);
+            this.isLoadingResults = false;
+            this.notifierService.notify('success',
+                this.translateService.instant('PAGE.K8S.NODEUPDATEDSUCCESSFULLY'));
+        }, (error: ERRORDATA) => {
+            this.restService.handleError(error, 'post');
+            this.isLoadingResults = false;
+        });
+    }
+    /** Used to get the AbstractControl of controlName passed @private */
+    private getFormControl(controlName: string): AbstractControl {
+        // eslint-disable-next-line security/detect-object-injection
+        return this.nodeForm.controls[controlName];
+    }
+}
index 8858311..b2661a2 100644 (file)
@@ -28,10 +28,9 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
     <div class="col-auto me-auto">
         <nav class="custom-items-config">
             <span><i class="fas fa-clock text-success"></i>{{operationalStateFirstStep}}</span>
-            <span><i class="fas fa-spinner text-warning"></i>{{operationalStateSecondStep}}</span>
-            <span><i class="fas fa-spinner text-danger"></i>{{operationalStateThirdStep}}</span>
-            <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateFourthStep}}</span>
-            <span><i class="fas fa-times-circle text-warning"></i>{{operationalStateFifthStep}}</span>
+            <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateSecondStep}}</span>
+            <span><i class="fas fa-spinner text-warning"></i>{{operationalStateThirdStep}}</span>
+            <span><i class="fas fa-ban text-danger"></i>{{operationalStateFourthStep}}</span>
         </nav>
     </div>
     <page-per-row class="me-2" (pagePerRow)="onChange($event)"></page-per-row>
index 702d8e6..bf6e122 100644 (file)
@@ -70,9 +70,6 @@ export class OKAPackageComponent implements OnInit {
     /** operational State failed deletion data @public */
     public operationalStateFourthStep: string = CONFIGCONSTANT.k8OperationalStateFourthStep;
 
-    /** operational State failed creation data @public */
-    public operationalStateFifthStep: string = CONFIGCONSTANT.k8OperationalStateFifthStep;
-
     /** Check the loading results @public */
     public isLoadingResults: boolean = true;
 
@@ -125,7 +122,7 @@ export class OKAPackageComponent implements OnInit {
             name: { title: this.translateService.instant('NAME'), width: '15%', sortDirection: 'asc' },
             identifier: { title: this.translateService.instant('IDENTIFIER'), width: '20%' },
             state: {
-                title: this.translateService.instant('GITSTATE'), width: '15%', type: 'html',
+                title: this.translateService.instant('STATE'), width: '15%', type: 'html',
                 filter: {
                     type: 'list',
                     config: {
@@ -134,34 +131,27 @@ export class OKAPackageComponent implements OnInit {
                             { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
                             { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
                             { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep },
-                            { value: this.operationalStateThirdStep, title: this.operationalStateFifthStep }
+                            { value: this.operationalStateThirdStep, title: this.operationalStateFourthStep }
                         ]
                     }
                 },
                 valuePrepareFunction: (cell: VNFD, row: VNFD): string => {
                     if (row.state === this.operationalStateFirstStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-clock text-success"></i>
-                                 </span>`;
+                                   <i class="fas fa-clock text-success"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateSecondStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-warning"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateThirdStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-spinner text-danger"></i>
-                                 </span>`;
+                                   <i class="fas fa-times-circle text-danger"></i>
+                                   </span>`;
                     } else if (row.state === this.operationalStateFourthStep) {
                         return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-danger"></i>
-                                 </span>`;
-                    } else if (row.state === this.operationalStateFifthStep) {
-                        return `<span class="icon-label" title="${row.state}">
-                                 <i class="fas fa-times-circle text-warning"></i>
-                                 </span>`;
+                                   <i class="fas fa-ban text-danger"></i>
+                                   </span>`;
                     } else {
-                        return `<span>${row.state}</span>`;
+                        return `<span class="icon-label" title="${row.state}">
+                                   <i class="fas fa-spinner text-warning"></i>
+                                   </span>`;
                     }
                 }
             },
@@ -218,7 +208,7 @@ export class OKAPackageComponent implements OnInit {
             onboardingState: okadpackagedata._admin.onboardingState,
             usageState: okadpackagedata._admin.usageState,
             created: this.sharedService.convertEpochTime(Number(okadpackagedata._admin.created)),
-            state: okadpackagedata.state
+            state: okadpackagedata.resourceState
         };
     }
     /** Handle compose new oka package method  @public */
index 007b0ab..be8081e 100644 (file)
@@ -36,9 +36,12 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
       <label class="col-sm-12 col-form-label mandatory-label"
         [ngClass]="{'text-danger': packagesForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' |
         translate}}</label>
-      <label class="col-sm-6 col-form-label" *ngIf="!template && !oka">{{'PACKAGE' | translate}} {{'NAME' | translate}}*</label>
-      <label class="col-sm-6 col-form-label" *ngIf="!template && params.page === 'oka-packages'">{{'PACKAGE' | translate}} {{'NAME' | translate}}*</label>
-      <label class="col-sm-6 col-form-label" *ngIf="!template && params.page === 'oka-packages-edit'">{{'PACKAGE' | translate}} {{'NAME' | translate}}</label>
+      <label class="col-sm-6 col-form-label" *ngIf="!template && !oka">{{'PACKAGE' | translate}} {{'NAME' |
+        translate}}*</label>
+      <label class="col-sm-6 col-form-label" *ngIf="!template && params.page === 'oka-packages'">{{'PACKAGE' |
+        translate}} {{'NAME' | translate}}*</label>
+      <label class="col-sm-6 col-form-label" *ngIf="!template && params.page === 'oka-packages-edit'">{{'PACKAGE' |
+        translate}} {{'NAME' | translate}}</label>
       <label class="col-sm-6 col-form-label" *ngIf="template">{{'NAME' | translate}}*</label>
       <div class="col-sm-6">
         <input type="text" class="form-control" placeholder="{{'NAME' | translate}}" formControlName="name" id="name"
@@ -81,7 +84,7 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
       <label class="col-sm-6 col-form-label">{{'CONFIG' | translate}}*</label>
       <div class="col-sm-6">
         <textarea rows="10" cols="50" class="form-control" placeholder="{{'YAMLCONFIG' | translate}}"
-          formControlName="config" id="config"></textarea>
+          formControlName="config" id="config" [ngClass]="{ 'is-invalid': submitted && f.config.errors }"></textarea>
         <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
         <div class="custom-file">
           <input type="file" #fileInputConfig class="fileupload custom-file-input"
@@ -91,7 +94,8 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
     </div>
     <div class="form-group row mb-3" *ngIf="oka">
       <label class="col-sm-6 col-form-label" *ngIf="params.page === 'oka-packages'">{{'PACKAGE' | translate}}*</label>
-      <label class="col-sm-6 col-form-label" *ngIf="params.page === 'oka-packages-edit'">{{'PACKAGE' | translate}}</label>
+      <label class="col-sm-6 col-form-label" *ngIf="params.page === 'oka-packages-edit'">{{'PACKAGE' |
+        translate}}</label>
       <div class="col-sm-6">
         <label for="fileInput" class="custom-file-upload" *ngIf="this.params.page === 'oka-packages-edit'">
           <input type="file" #fileInput class="fileupload custom-file-input" formControlName="package"
index a8114d0..d294f7f 100644 (file)
@@ -30,7 +30,6 @@ 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';
@@ -204,6 +203,7 @@ export class ComposePackages implements OnInit {
       this.getNsdPackageDetails();
       this.getFormControl('profile_type').disable();
       this.getFormControl('description').disable();
+      this.getFormControl('package').disable();
     } else if (this.params.page === 'ns-config-template-edit') {
       this.template = true;
       this.oka = false;
@@ -211,6 +211,7 @@ export class ComposePackages implements OnInit {
       this.getFormControl('profile_type').disable();
       this.getFormControl('nsdId').disable();
       this.getFormControl('description').disable();
+      this.getFormControl('package').disable();
     } else if (this.params.page === 'oka-packages') {
       this.oka = true;
       this.template = false;
@@ -241,7 +242,7 @@ export class ComposePackages implements OnInit {
     this.packagesForm = this.formBuilder.group({
       name: ['', [Validators.required]],
       nsdId: [null, [Validators.required]],
-      config: [null],
+      config: [null, [Validators.required]],
       profile_type: [null],
       description: ['', [Validators.required]],
       package: ['']
@@ -269,7 +270,7 @@ export class ComposePackages implements OnInit {
 
   /** Get NSD Package details @public */
   public getNsdPackageDetails(): void {
-    this.restService.getResource(environment.OKAPACKAGES_URL)
+    this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL)
       .subscribe((nsdPackageData: []): void => {
         nsdPackageData.forEach((nsData: VNFD): void => {
           const names: {} = {
@@ -336,6 +337,12 @@ export class ComposePackages implements OnInit {
     };
     this.addNullValueForInvalidFiles();
     this.sharedService.cleanForm(this.packagesForm);
+    if (this.params.page === 'ns-config-template-edit' || this.params.page === 'ns-config-template') {
+      if (this.packagesForm.value.config.trim() === '' || isNullOrUndefined(this.packagesForm.value.config)) {
+        this.packagesForm.controls.config.setErrors({ configIsEmpty: true });
+        this.packagesForm.get('config').setValue(this.packagesForm.get('config').value.trim());
+      }
+    }
     if (!this.packagesForm.invalid) {
       this.isLoadingResults = true;
       if (this.params.page === 'ns-package' || this.params.page === 'vnf-package') {
@@ -443,16 +450,12 @@ export class ComposePackages implements OnInit {
       url: urlHeader,
       httpOptions: { headers: this.headers }
     };
-    if (isNullOrUndefined(this.packagesForm.value.config) || this.packagesForm.value.config === '') {
-      delete this.packagesForm.value.config;
+    const validJSON: boolean = this.sharedService.checkJson(this.packagesForm.value.config);
+    if (validJSON) {
+      this.packagesForm.value.config = JSON.parse(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 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);
index c7a6c62..7c90b6e 100644 (file)
@@ -28,9 +28,14 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
     <i class="fas fa-times-circle text-danger"></i>
   </button>
 </div>
-<div class="modal-body">
-  <span>{{'DELETECONFIRMPOPUPMESSAGE' | translate}} <b>{{ this.title }}</b> ?</span>
+<div class="modal-body" *ngIf="createdbyosm === 'false'; else Deletemessage">
+  <span>{{'DEREGISTERCONFIRMPOPUPMESSAGE' | translate}} <b>{{ this.title }}</b> ?</span>
 </div>
+<ng-template #Deletemessage>
+  <div class="modal-body">
+    <span>{{'DELETECONFIRMPOPUPMESSAGE' | translate}} <b>{{ this.title }}</b> ?</span>
+  </div>
+</ng-template>
 <div class="modal-footer">
   <button (click)="activeModal.close()" class="btn btn-danger">{{'CANCEL' | translate}}</button>
   <button *ngIf="!isPage; else multiDelete" (click)="deleteData();" class="btn btn-primary">{{'OK' | translate}}</button>
index f65712d..a54b67e 100644 (file)
@@ -132,7 +132,11 @@ export class DeleteComponent {
       if (sessionStorage.getItem('clusterType') === 'Registered') {
         this.isRegisterPage = true;
       }
-      this.createdbyosm = data.createdbyosm;
+      if (data.createdbyosm === 'NO' || data.createdbyosm === 'false') {
+        this.createdbyosm = 'false';
+      } else {
+        this.createdbyosm = 'true';
+      }
       this.bootstrap = data.bootstrap;
       this.key = data.key;
       if (!isNullOrUndefined(this.params)) {
@@ -170,6 +174,11 @@ export class DeleteComponent {
     } else if (data.productName !== undefined) {
       this.title = data.productName;
     }
+    if (data.createdbyosm === 'NO' || data.createdbyosm === 'false') {
+      this.createdbyosm = 'false';
+    } else {
+      this.createdbyosm = 'true';
+    }
   }
   /** Generate Delete url from data @public */
   // eslint-disable-next-line complexity
@@ -184,6 +193,10 @@ export class DeleteComponent {
       } else if (this.params.page === 'instantiateNS') {
         this.deleteURL = environment.NSINSTANCESTERMINATE_URL;
         this.notifyMessage = 'DELETEDSUCCESSFULLY';
+      } else if (this.params.page === 'card-node') {
+        this.title = this.params.name;
+      } else if (this.params.page === 'card-ksu') {
+        this.title = this.params.name;
       }
     }
     if (data.page === 'ns-package') {
@@ -249,6 +262,8 @@ export class DeleteComponent {
     } else if (data.page === 'k8-cluster') {
       this.forceDelete = this.params.forceDeleteType;
       this.page = data.page;
+    } else if (data.page === 'k8s-node') {
+      this.deleteURL = environment.K8SCREATECLUSTER_URL + '/' + data.cluster_id + '/node';
     }
   }
   /** Generate Data function @public */
@@ -265,24 +280,27 @@ export class DeleteComponent {
         }
       }
       deletingURl = this.deleteURL + '/' + this.id + '?FORCE=true';
-      this.notifyMessage = 'DELETEDSUCCESSFULLY';
+      this.notifyMessage =  'DELETELOADMESSAGE';
     } else if (this.page === 'k8-cluster') {
       if (this.createdbyosm === 'true') {
         this.deleteURL = environment.K8SCREATECLUSTER_URL;
         deletingURl = this.deleteURL + '/' + this.id;
       } else {
-        if (this.bootstrap === false && this.key === true) {
-          this.deleteURL = environment.K8SCLUSTER_URL;
-          deletingURl = this.deleteURL + '/' + this.id;
-        } else if (this.bootstrap === false && this.key === false) {
-          this.deleteURL = environment.K8SCREATECLUSTER_URL;
-          deletingURl = this.deleteURL + '/' + this.id + '/deregister';
-        }
-        else if (this.bootstrap === true) {
+        if (this.key === false) {
           this.deleteURL = environment.K8SCREATECLUSTER_URL;
           deletingURl = this.deleteURL + '/' + this.id + '/deregister';
+        } else if (this.key === true) {
+          this.deleteURL = environment.K8SCLUSTER_URL;
+          deletingURl = this.deleteURL + '/' + this.id;
         }
       }
+    } else if (!isNullOrUndefined(this.params)) {
+      if (this.params.page === 'card-node') {
+        this.createdbyosm = 'true';
+        deletingURl = environment.K8SCREATECLUSTER_URL + '/' + this.params.cluster_id + '/nodegroup' + '/' + this.params.id;
+      } else if (this.params.page === 'card-ksu') {
+        deletingURl = environment.KSU_URL + '/' + this.params.id;
+      }
     } else {
       deletingURl = this.deleteURL + '/' + this.id;
     }
index c7627d8..74833a6 100644 (file)
@@ -16,11 +16,11 @@ limitations under the License.
 Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
 -->
 <div class="btn-group list action" role="group">
-  <button type="button" class="btn btn-primary" (click)="deleteoka(false)"
+  <button [disabled]="state != 'READY'" type="button" class="btn btn-primary" (click)="deleteoka(false)"
     placement="top" container="body" ngbTooltip="{{'DELETE' | translate}}">
     <i class="far fa-trash-alt icons"></i>
   </button>
-  <button [disabled]="state != 'CREATED'" type="button" class="btn btn-primary" (click)="okaEdit()" placement="top"
+  <button [disabled]="state != 'READY'" type="button" class="btn btn-primary" (click)="okaEdit()" placement="top"
     container="body" ngbTooltip="{{'EDIT' | translate}}">
     <i class="far fa-edit icons"></i>
   </button>
@@ -29,4 +29,4 @@ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
     <i class="fas fa-trash-alt icons text-danger" title="delete"></i>
   </button>
 </div>
-<app-loader [waitingMessage]="message" *ngIf="isLoadingDownloadResult"></app-loader>
\ No newline at end of file
+<app-loader [waitingMessage]="message" *ngIf="isLoadingDownloadResult"></app-loader>
index 6c21ac5..b3c0fbe 100644 (file)
@@ -201,10 +201,10 @@ export class ShowInfoComponent implements OnInit {
       } else {
         if (this.params.bootstrap === true) {
           this.url = environment.K8SCREATECLUSTER_URL + '/' + this.params.id;
-        } else if (this.params.bootstrap === false && this.params.key === false) {
-          this.url = environment.K8SCREATECLUSTER_URL + '/' + this.params.id;
-        } else if (this.params.bootstrap === false && this.params.key === true) {
+        } else if (this.params.createdbyosm === 'NO') {
           this.url = environment.K8SCLUSTER_URL + '/' + this.params.id;
+        } else if (this.params.key === true) {
+          this.url = environment.K8SCREATECLUSTER_URL + '/' + this.params.id;
         }
       }
       this.restService.getResource(this.url).subscribe((k8sclusterOpn: {}[]) => {
@@ -215,6 +215,26 @@ export class ShowInfoComponent implements OnInit {
       }, () => {
         this.isLoadingResults = false;
       });
+    } else if (this.params.page === 'k8s-node') {
+      this.url = environment.K8SCREATECLUSTER_URL + '/' + this.params.cluster_id + '/nodegroup' + '/' + this.params.id;
+      this.restService.getResource(this.url).subscribe((k8sclusterOpn: {}[]) => {
+        this.defaults['text/json'] = JSON.stringify(k8sclusterOpn, null, '\t');
+      }, (error: ERRORDATA) => {
+        this.isLoadingResults = false;
+        this.restService.handleError(error, 'get');
+      }, () => {
+        this.isLoadingResults = false;
+      });
+    } else if (this.params.page === 'k8s-ksu') {
+      this.url = environment.KSU_URL + '/' + this.params.id;
+      this.restService.getResource(this.url).subscribe((k8sclusterOpn: {}[]) => {
+        this.defaults['text/json'] = JSON.stringify(k8sclusterOpn, null, '\t');
+      }, (error: ERRORDATA) => {
+        this.isLoadingResults = false;
+        this.restService.handleError(error, 'get');
+      }, () => {
+        this.isLoadingResults = false;
+      });
     } else if (this.params.page === 'k8s-repo') {
       this.restService.getResource(environment.K8REPOS_URL + '/' +
         this.params.id).subscribe((k8srepoOpn: {}[]) => {
index ac668eb..e71f63a 100644 (file)
@@ -96,6 +96,7 @@
     "DELETEDSUCCESSFULLY": "Erfolgreich gelöscht",
     "SESSIONEXPIRY": "Sitzung abgelaufen, bitte erneut anmelden",
     "DELETECONFIRMPOPUPMESSAGE": "Möchten Sie wirklich löschen?",
+    "DEREGISTERCONFIRMPOPUPMESSAGE": "Sind Sie sicher, dass Sie sich abmelden möchten",
     "DELETELOADERMESSAGE": "Bitte warten Sie, während der Löschvorgang ausgeführt wird",
     "DELETELOADMESSAGE": "Bitte warten Sie, während der Löschvorgang ausgeführt wird",
     "WARNINGMESSAGE": "Es können nicht mehr als 25 Instanzen gelöscht werden",
             "VERTICALSCALING": "Vertikale Skalierung",
             "BOOTSTRAP": "Bootstrap",
             "BOOTSTRAPINFO": "Bereite dich auf GitOps vor",
-             "UPDATECLUSTER": "Cluster aktualisieren"
+            "ROLENAME": "Rollenname",
+            "NODEROLE": "Knotenrolle",
+            "PRIVATESUBNET": "Privates Subnetz",
+            "PUBLICSUBNET": "Öffentliches Subnetz",
+            "CREATECONTROLPLANE": "Steuerebene EKS erstellen",
+            "CREATENODEGROUP": "Knotengruppe erstellen",
+            "ADDNODE": "Knotengruppe hinzufügen",
+            "EDITNODE": "Knotengruppe bearbeiten",
+            "DELETEALLNODE": "Alle Knoten löschen",
+            "CLUSTER": "Cluster",
+            "NODE": "Knotengruppe",
+            "NODECREATEDSUCCESSFULLY": "Knotengruppe erfolgreich erstellt",
+            "NODEUPDATEDSUCCESSFULLY": "Knotengruppe erfolgreich aktualisiert",
+            "SECURITYGROUP": "Sicherheitsgruppe",
+            "PACKAGENAME": "Paketname",
+            "PACKAGEPATH": "Paketpfad",
+            "DELETEALLKSU": "Alle KSU löschen",
+            "VERSIONUPGRADE": "Versions-Upgrade",
+            "K8SSCALING": "Skalierung",
+            "UPDATECLUSTER": "Cluster aktualisieren",
+            "DETAILS": "Details",
+            "SUBNET": "Subnetz"
         },
         "OSMREPO": {
             "MENUOSMREPO": "OSM-Repositorys",
index 427561d..9dfabf3 100644 (file)
@@ -96,6 +96,7 @@
     "DELETEDSUCCESSFULLY": "{{title}} deleted successfully",
     "SESSIONEXPIRY": "Session expired, please login again",
     "DELETECONFIRMPOPUPMESSAGE": "Are you sure want to delete",
+    "DEREGISTERCONFIRMPOPUPMESSAGE": "Are you sure want to deregister",
     "DELETELOADERMESSAGE": "Please wait while {{title}} deletion is in progress",
     "DELETELOADMESSAGE": "Please wait while deletion is in progress",
     "WARNINGMESSAGE": "Cannot delete more than 25 instances",
             "VERTICALSCALING": "Vertical Scaling",
             "BOOTSTRAP": "Bootstrap",
             "BOOTSTRAPINFO": "Prepare for GitOps",
-            "UPDATECLUSTER": "Update Cluster"
+            "ROLENAME": "Role Name",
+            "NODEROLE": "Node Role",
+            "PRIVATESUBNET": "Private Subnet",
+            "PUBLICSUBNET": "Public Subnet",
+            "CREATECONTROLPLANE": "Create Control Plane EKS",
+            "CREATENODEGROUP": "Create Node Group",
+            "ADDNODE": "Add Node Group",
+            "EDITNODE": "Edit Node Group",
+            "DELETEALLNODE": "Delete All Nodes",
+            "CLUSTER": "Cluster",
+            "NODE": "Node Group",
+            "NODECREATEDSUCCESSFULLY": "Node Group Created Successfully",
+            "NODEUPDATEDSUCCESSFULLY": "Node Group Updated Successfully",
+            "SECURITYGROUP": "Security Group",
+            "PACKAGENAME": "Package Name",
+            "PACKAGEPATH": "Package Path",
+            "DELETEALLKSU": "Delete All KSU",
+            "VERSIONUPGRADE": "Version Upgrade",
+            "K8SSCALING": "Scaling",
+            "UPDATECLUSTER": "Update Cluster",
+            "DETAILS": "Details",
+            "SUBNET": "Subnet"
         },
         "OSMREPO": {
             "MENUOSMREPO": "OSM Repositories",
index c5a9959..a4e5a64 100644 (file)
@@ -96,6 +96,7 @@
     "DELETEDSUCCESSFULLY": "Eliminada correctamente",
     "SESSIONEXPIRY": "Sesión expirada, por favor ingrese de nuevo",
     "DELETECONFIRMPOPUPMESSAGE": "¿Seguro que lo quiere eliminar?",
+    "DEREGISTERCONFIRMPOPUPMESSAGE": "¿Está seguro de que desea darse de baja?",
     "DELETELOADERMESSAGE": "Por favor, espere mientras la eliminación está en progreso",
     "DELETELOADMESSAGE": "Por favor, espere mientras la eliminación está en progreso",
     "WARNINGMESSAGE": "No se pueden eliminar más de 25 instancias",
             "VERTICALSCALING": "Escalado Vertical",
             "BOOTSTRAP": "Bootstrap",
             "BOOTSTRAPINFO": "Prepárate para GitOps",
-             "UPDATECLUSTER": "Actualizar clúster"
+            "ROLENAME": "Nombre del rol",
+            "NODEROLE": "Rol del nodo",
+            "PRIVATESUBNET": "Subred privada",
+            "PUBLICSUBNET": "Subred pública",
+            "CREATECONTROLPLANE": "Crear plano de control EKS",
+            "CREATENODEGROUP": "Crear grupo de nodos",
+            "ADDNODE": "Agregar grupo de nodos",
+            "EDITNODE": "Editar grupo de nodos",
+            "DELETEALLNODE": "Eliminar todos los nodos",
+            "CLUSTER": "Clúster",
+            "NODE": "Grupo de nodos",
+            "NODECREATEDSUCCESSFULLY": "Grupo de nodos creado con éxito",
+            "NODEUPDATEDSUCCESSFULLY": "Grupo de nodos actualizado con éxito",
+            "SECURITYGROUP": "Grupo de seguridad",
+            "PACKAGENAME": "Nombre del paquete",
+            "PACKAGEPATH": "Ruta del paquete",
+            "DELETEALLKSU": "Eliminar todos los KSU",
+            "VERSIONUPGRADE": "Actualización de versión",
+            "K8SSCALING": "Escalado",
+            "UPDATECLUSTER": "Actualizar clúster",
+            "DETAILS": "Detalles",
+            "SUBNET": "Subred"
         },
         "OSMREPO": {
             "MENUOSMREPO": "Repositorios OSM",
index 538661a..5bfb04b 100644 (file)
@@ -96,6 +96,7 @@
     "DELETEDSUCCESSFULLY": "Apagado com sucesso",
     "SESSIONEXPIRY": "Sessão expirada, faça o login novamente",
     "DELETECONFIRMPOPUPMESSAGE": "Tem certeza de que deseja excluir",
+    "DEREGISTERCONFIRMPOPUPMESSAGE": "Tem certeza de que deseja cancelar o registro?",
     "DELETELOADERMESSAGE": "Aguarde enquanto a exclusão está em andamento",
     "DELETELOADMESSAGE": "Aguarde enquanto a exclusão está em andamento",
     "WARNINGMESSAGE": "Não é possível excluir mais de 25 instâncias",
             "VERTICALSCALING": "Escalonamento Vertical",
             "BOOTSTRAP": "Bootstrap",
             "BOOTSTRAPINFO": "Prepare-se para GitOps",
-             "UPDATECLUSTER": "Atualizar cluster"
+            "ROLENAME": "Nome do papel",
+            "NODEROLE": "Função do nó",
+            "PRIVATESUBNET": "Sub-rede privada",
+            "PUBLICSUBNET": "Sub-rede pública",
+            "CREATECONTROLPLANE": "Criar plano de controle EKS",
+            "CREATENODEGROUP": "Criar grupo de nós",
+            "ADDNODE": "Adicionar grupo de nós",
+            "EDITNODE": "Editar grupo de nós",
+            "DELETEALLNODE": "Excluir todos os nós",
+            "CLUSTER": "Cluster",
+            "NODE": "Grupo de nós",
+            "NODECREATEDSUCCESSFULLY": "Grupo de nós criado com sucesso",
+            "NODEUPDATEDSUCCESSFULLY": "Grupo de nós atualizado com sucesso",
+            "SECURITYGROUP": "Grupo de segurança",
+            "PACKAGENAME": "Nome do pacote",
+            "PACKAGEPATH": "Caminho do pacote",
+            "DELETEALLKSU": "Excluir todos os KSU",
+            "VERSIONUPGRADE": "Atualização de versão",
+            "K8SSCALING": "Escalonamento",
+            "UPDATECLUSTER": "Atualizar cluster",
+            "DETAILS": "Detalhes",
+            "SUBNET": "Sub-rede"
         },
         "OSMREPO": {
             "MENUOSMREPO": "Repositórios OSM",
index fc19af5..bae6ff1 100644 (file)
@@ -88,6 +88,7 @@ export const environment = {
     OSMREPOS_URL: OSM_ADMIN_ENDPOINT + 'osmrepos',
     NSCONFIGTEMPLATE_URL: OSM_NSD_ENDPOINT + 'ns_config_template',
     K8SCREATECLUSTER_URL: OSM_CLUSTER_ENDPOINT + 'clusters',
+    CONTROLPLANECLUSTER_URL: OSM_CLUSTER_ENDPOINT + 'control_planes',
     K8SINFRACONFIGPROFILE_URL: OSM_CLUSTER_ENDPOINT + 'infra_config_profiles',
     K8SINFRACONTROLLERPROFILE_URL: OSM_CLUSTER_ENDPOINT + 'infra_controller_profiles',
     K8SAPPPROFILE_URL: OSM_CLUSTER_ENDPOINT + 'app_profiles',
index 1e4f45c..d1fcaf4 100644 (file)
@@ -88,6 +88,7 @@ export const environment = {
     OSMREPOS_URL: OSM_ADMIN_ENDPOINT + 'osmrepos',
     NSCONFIGTEMPLATE_URL: OSM_NSD_ENDPOINT + 'ns_config_template',
     K8SCREATECLUSTER_URL: OSM_CLUSTER_ENDPOINT + 'clusters',
+    CONTROLPLANECLUSTER_URL: OSM_CLUSTER_ENDPOINT + 'control_planes',
     K8SINFRACONFIGPROFILE_URL: OSM_CLUSTER_ENDPOINT + 'infra_config_profiles',
     K8SINFRACONTROLLERPROFILE_URL: OSM_CLUSTER_ENDPOINT + 'infra_controller_profiles',
     K8SAPPPROFILE_URL: OSM_CLUSTER_ENDPOINT + 'app_profiles',
index 001d970..f29ee68 100644 (file)
@@ -70,14 +70,14 @@ export enum CONFIGCONSTANT {
     sdnOperationalStateFirstStep = 'PROCESSING',
     sdnOperationalStateStateSecondStep = 'ENABLED',
     sdnOperationalStateThirdStep = 'ERROR',
-    k8OperationalStateFirstStep = 'CREATED',
-    k8OperationalStateStateSecondStep = 'IN_CREATION',
-    k8OperationalStateThirdStep = 'IN_DELETION',
-    k8OperationalStateFourthStep = 'FAILED_DELETION',
-    k8OperationalStateFifthStep = 'FAILED_CREATION',
-    k8OperationalStateSixthStep = 'N/A',
-    clusterModeFirstStep = 'MANAGED',
-    clusterModeSecondStep = 'REGISTERED',
+    k8OperationalStateFirstStep = 'READY',
+    k8OperationalStateStateSecondStep = 'ERROR',
+    k8OperationalStateThirdStep = 'IN_PROGRESS',
+    k8OperationalStateFourthStep = 'N/A',
+    k8OperationalStateFifthStep = 'ENABLED',
+    k8OperationalStateSixthStep = 'DEGRADED',
+    clusterModeFirstStep = 'managed',
+    clusterModeSecondStep = 'registered',
     done = 'done',
     close = 'close',
     userActive = 'active',
@@ -137,6 +137,8 @@ export interface URLPARAMS {
     createdbyosm?: string;
     bootstrap?: boolean;
     key?: boolean;
+    cluster_mode?: string;
+    cluster_id?: string;
     operationType?: string;
 }
 /** Handle the Delete params */
@@ -152,6 +154,7 @@ export interface DELETEPARAMS {
     createdbyosm?: string;
     bootstrap?: boolean;
     key?: boolean;
+    cluster_id?: string;
 }
 
 /** Interface for the Delete Details */
index 06a13b2..0843033 100644 (file)
 
 /** Interface for K8SCLUSTERDATA */
 export interface K8SCLUSTERDATA {
-    credentials: Credentials;
+    credentials?: Credentials;
+    description?: string;
+    k8s_version?: number;
+    name?: string;
+    namespace?: string;
+    nets?: Nets;
+    schema_version?: string;
+    vim_account?: string;
+    _admin?: Admin;
+    _id?: string;
+    state?: string;
+    resourceState?: string;
+    created?: string;
+    bootstrap?: boolean;
+    key?: string;
+    cloud_type?: string;
+    cluster_mode?: string;
+    node_count?: number;
+    node_size?: string;
+    ksu_count?: number;
+    cluster_name?: string;
+    private_subnet?: string[];
+    public_subnet?: string[];
+    cluster_id?: string;
+    count?: number;
+    package_name?: string;
+    package_path?: string;
+    data?: K8SNODEDATA[];
+}
+/** Interface for K8SCLUSTERDATA */
+export interface K8SNODEDATA {
     description: string;
-    k8s_version: number;
     name: string;
-    namespace: string;
-    nets: Nets;
-    schema_version: string;
-    vim_account: string;
+    package_name?: string;
+    package_path?: string;
     _admin: Admin;
     _id: string;
     state?: string;
     resourceState?: string;
-    created?: string;
-    bootstrap?: boolean;
-    key?: string;
     node_count?: number;
-    node_size?: number;
+    node_size?: string;
 }
 /** Interface for K8SCLUSTERDATA */
 export interface K8SREPODATA {
@@ -117,10 +141,10 @@ export interface K8SCLUSTERDATADISPLAY {
     name: string;
     identifier: string;
     operationalState?: string;
-    version: number;
+    version?: number;
     created?: string;
     modified?: string;
-    pageType: string;
+    pageType?: string;
     description?: string;
     default?: boolean;
     state?: string;
@@ -128,6 +152,14 @@ export interface K8SCLUSTERDATADISPLAY {
     bootstrap?: boolean;
     key?: boolean;
     clusterMode?: string;
+    nodeCount?: number;
+    nodeSize?: string;
+    cloud_type?: string;
+    cluster_mode?: string;
+    cluster_name?: string;
+    cluster_id?: string;
+    package_name?: string;
+    package_path?: string;
 }
 /** Interface for the K8SCLUSTERDATA Return to Display */
 export interface K8SREPODATADISPLAY {
@@ -144,6 +176,9 @@ export interface K8SREPODATADISPLAY {
     createdbyosm?: boolean;
     bootstrap?: boolean;
     key?: boolean;
+    cloud_type?: string;
+    cluster_mode?: string;
+    cluster_id?: string;
 }
 
 /** Interface for the Create cluster */
@@ -187,6 +222,9 @@ export interface INFRACONFIGPAYLOAD {
     createdbyosm?: boolean;
     bootstrap?: boolean;
     key?: boolean;
+    cluster_mode?: string;
+    cluster_id?: string;
+    resourceState?: string;
 }
 
 /** Interface for the KSU */
index 1e60f28..f3dbf66 100644 (file)
@@ -221,6 +221,16 @@ export const MENU_ITEMS: MENUITEMS[] = [
                 menuName: 'PAGE.K8S.MENUK8SREPO',
                 isChildExists: false
             },
+            {
+                liClass: '',
+                anchorTagClass: 'link',
+                routerLink: '/k8s/ksu',
+                routerLinkActive: childActiveClass,
+                routerLinkActiveOptions: false,
+                icon: 'fas fa-anchor',
+                menuName: 'PAGE.K8S.KSU',
+                isChildExists: false
+            },
             {
                 liClass: '',
                 anchorTagClass: 'link',
@@ -260,16 +270,6 @@ export const MENU_ITEMS: MENUITEMS[] = [
                 icon: 'fas fa-archive',
                 menuName: 'PAGE.K8S.RESOURCE',
                 isChildExists: false
-            },
-            {
-                liClass: '',
-                anchorTagClass: 'link',
-                routerLink: '/k8s/ksu',
-                routerLinkActive: childActiveClass,
-                routerLinkActiveOptions: false,
-                icon: 'fas fa-anchor',
-                menuName: 'PAGE.K8S.KSU',
-                isChildExists: false
             }
         ]
     },
index 2334538..022739d 100644 (file)
@@ -86,6 +86,7 @@ export interface VNFD {
     kdu?: [];
     name?: string;
     state?: string;
+    resourceState?: string;
     profile_type?: string;
 }
 /** Interface for DF */
index 2a87382..ed14e47 100644 (file)
@@ -20,7 +20,7 @@
  */
 import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
 import { EventEmitter, Injectable, Output } from '@angular/core';
-import { FormArray, FormGroup } from '@angular/forms';
+import { FormArray, FormControl, FormGroup } from '@angular/forms';
 import { Router } from '@angular/router';
 import { TranslateService } from '@ngx-translate/core';
 import {
@@ -370,24 +370,27 @@ export class SharedService {
     }
 
     /** Clean the form before submit @public */
-    public cleanForm(formGroup: FormGroup, formName?: String): void {
+    public cleanForm(formGroup: FormGroup | FormArray, formName?: string): void {
         Object.keys(formGroup.controls).forEach((key: string) => {
-            if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'config') {
-                // eslint-disable-next-line @typescript-eslint/no-shadow
-                for (const { item, index } of (formGroup.get(key).value).map((item: {}, index: number) => ({ item, index }))) {
-                    // eslint-disable-next-line security/detect-object-injection
-                    const newFormGroup: FormGroup = (formGroup.get(key) as FormArray).controls[index] as FormGroup;
-                    this.cleanForm(newFormGroup);
-                }
-            } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'config') {
-                if (!Array.isArray(formGroup.get(key).value)) {
-                    if (typeof formGroup.get(key).value === 'string') {
-                        formGroup.get(key).setValue(formGroup.get(key).value.trim());
+            const control = formGroup.get(key);
+            if (control instanceof FormArray && key !== 'config') {
+                control.controls.forEach((ctrl, index) => {
+                    if (ctrl instanceof FormGroup) {
+                        this.cleanForm(ctrl);
+                    } else if (ctrl instanceof FormControl) {
+                        if (typeof ctrl.value === 'string') {
+                            ctrl.setValue(ctrl.value.trim());
+                        }
                     }
+                });
+            } else if (control instanceof FormGroup && key !== 'config') {
+                this.cleanForm(control);
+            } else if (control instanceof FormControl && control.value !== undefined && control.value !== null) {
+                if (typeof control.value === 'string') {
+                    control.setValue(control.value.trim());
                 }
             } else if (key === 'config' && formName === 'vim') {
-                const newFormGroup: FormGroup = formGroup.get(key) as FormGroup;
-                this.cleanForm(newFormGroup);
+                this.cleanForm(control as FormGroup);
             }
         });
     }
index 576198b..6d1c59e 100644 (file)
         "KSUAddComponent": ["src/app/k8s/k8s-ksu/ksu-add/KSUAddComponent"],
         "OkaPackageComponent": ["src/app/packages/oka-packages/OKAPackageComponent"],
         "OkaPackagesActionComponent": ["src/app/utilities/oka-packages-action/OkaPackagesActionComponent"],
+        "NodeAddComponent": ["src/app/k8s/node-add/NodeAddComponent"],
+        "K8sInfoComponent": ["src/app/k8s/k8s-info/K8sInfoComponent"],
       },
       "useDefineForClassFields": false
     }