Adding unlimited max value to VNF, NETWORK

Issue-ID: VID-726
Signed-off-by: Yoav Schneiderman <yoav.schneiderman@intl.att.com>
Change-Id: I0c3d503c8e4f6cb14081de8f6a619a67eee080b7
Signed-off-by: Yoav Schneiderman <yoav.schneiderman@intl.att.com>
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts
index 3483885..50bfa93 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts
@@ -3,9 +3,10 @@
 import {NgRedux} from '@angular-redux/store';
 import {ITreeNode} from "angular-tree-component/dist/defs/api";
 import {SdcUiServices} from "onap-ui-angular";
-import {IModalConfig} from "onap-ui-angular/dist/components/common";
+import {IModalConfig} from 'onap-ui-angular/dist/components/common';
 import {AppState} from "../../../shared/store/reducers";
 import {getTestBed, TestBed} from "@angular/core/testing";
+import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
 
 class MockAppStore<T> {
   getState(){
@@ -52,15 +53,23 @@
 
 class MockModalService<T> {}
 
+class MockFeatureFlagsService extends  FeatureFlagsService{
+  getAllFlags(): { [p: string]: boolean } {
+    return {};
+  }
+}
+
 describe('Drawing board tree service', () => {
   let injector;
   let service: DuplicateService;
   let store : NgRedux<AppState>;
+  let featureFlagsService : FeatureFlagsService;
   beforeAll(done => (async () => {
     TestBed.configureTestingModule({
       providers : [
         DuplicateService,
         LogService,
+        {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         {provide: NgRedux, useClass: MockAppStore},
         {provide: SdcUiServices.ModalService, useClass: MockModalService}
       ]
@@ -70,6 +79,7 @@
     injector = getTestBed();
     service = injector.get(DuplicateService);
     store = injector.get(NgRedux);
+    featureFlagsService = injector.get(FeatureFlagsService);
 
   })().then(done).catch(done.fail));
 
@@ -418,6 +428,11 @@
               }
 
             }
+          },
+          global : {
+            flags : {
+
+            }
           }
         }
       }
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts
index 5fb5f0b..847790d 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts
@@ -11,15 +11,18 @@
 import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
 import {changeInstanceCounter, duplicateBulkInstances} from "../../../shared/storeUtil/utils/general/general.actions";
 import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
+import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
+import {Utils} from "../../../shared/utils/utils";
 
 @Injectable()
 export class DuplicateService {
 
-  constructor(private _logService : LogService,  private _store: NgRedux<AppState>, modalService: SdcUiServices.ModalService) {
+  constructor(private _logService: LogService, private _store: NgRedux<AppState>, modalService: SdcUiServices.ModalService) {
     this.modalService = modalService;
   }
 
-  numberOfDuplicates:number;
+  numberOfDuplicates: number;
+
   setNumberOfDuplicates(numberOfDuplicates: number) {
     this.numberOfDuplicates = numberOfDuplicates;
   }
@@ -30,10 +33,9 @@
   storeKey: string = null;
   padding = '0000';
   modalService: SdcUiServices.ModalService;
-  store : NgRedux<AppState>;
-  existingNames : {[key: string] : any};
-  currentNode : ITreeNode = null;
-
+  store: NgRedux<AppState>;
+  existingNames: { [key: string]: any };
+  currentNode: ITreeNode = null;
 
 
   canDuplicate(node: ITreeNode): boolean {
@@ -41,25 +43,31 @@
     return node.data.type === 'VF' || node.data.type === 'VL';
   }
 
-  isEnabled(node: ITreeNode, store: NgRedux<AppState>, serviceId : string): boolean {
-    if(!_.isNil(node) && !_.isNil(node.data.menuActions['duplicate'])){
-      if(this.hasMissingData(node)) return false;
-      const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node);
-      const max : number = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][node.data.modelName].properties['max_instances'] || 1;
-      const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][node.data.modelUniqueId];
+  isEnabled(node: ITreeNode, store: NgRedux<AppState>, serviceId: string): boolean {
+    if (!_.isNil(node) && !_.isNil(node.data.menuActions['duplicate'])) {
+      if (this.hasMissingData(node)) return false;
+      const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
+      const flags = FeatureFlagsService.getAllFlags(store);
 
-      return max - currentExisting > 0;
-    }else {
+      const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][node.data.modelUniqueId];
+      const maxInstances = Utils.getMaxFirstLevel(store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][node.data.modelName].properties, flags);
+      if (_.isNil(maxInstances)) {
+        return true;
+      } else {
+        return maxInstances - currentExisting > 0;
+      }
+
+    } else {
       return false;
     }
   }
 
-  hasMissingData(node : ITreeNode): boolean {
-    if(!_.isNil(node)){
-      if(node.data.missingData) return true;
-      if(!_.isNil(node.data.children)){
-        for(let child of node.data.children) {
-          if(child.missingData){
+  hasMissingData(node: ITreeNode): boolean {
+    if (!_.isNil(node)) {
+      if (node.data.missingData) return true;
+      if (!_.isNil(node.data.children)) {
+        for (let child of node.data.children) {
+          if (child.missingData) {
             return true;
           }
         }
@@ -69,16 +77,22 @@
     return false;
   }
 
-  getRemainsInstance(modelId : string, modelName : string, serviceId : string, store: NgRedux<AppState>, node : ITreeNode) : number {
-    const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node);
-    const properties  = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][modelName].properties;
-    const currentExisting : number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][modelId];
-    return (!_.isNil(properties) && !_.isNil(properties['max_instances'])) ? properties['max_instances'] - currentExisting : null;
+  getRemainsInstance(modelId: string, modelName: string, serviceId: string, store: NgRedux<AppState>, node: ITreeNode): number {
+    const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
+    const properties = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][modelName].properties;
+    const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][modelId];
+
+    const flags = FeatureFlagsService.getAllFlags(store);
+    const maxInstances = Utils.getMaxFirstLevel(properties, flags);
+    if (_.isNil(maxInstances)) {
+      return 10;
+    } else {
+      return maxInstances - currentExisting;
+    }
   }
 
 
-
-  openDuplicateModal(currentServiceId: string, currentUuid: string, currentId: string, storeKey : string, numberOfDuplicate: number, _store : NgRedux<AppState>, node: ITreeNode): IModalConfig {
+  openDuplicateModal(currentServiceId: string, currentUuid: string, currentId: string, storeKey: string, numberOfDuplicate: number, _store: NgRedux<AppState>, node: ITreeNode): IModalConfig {
     this.currentInstanceId = currentId;
     this.currentServiceId = currentServiceId;
     this.maxNumberOfDuplicate = this.getRemainsInstance(currentUuid, currentId, currentServiceId, _store, node);
@@ -87,7 +101,7 @@
     this.currentNode = node;
 
 
-    return  {
+    return {
       size: SdcUiCommon.ModalSize.medium,
       title: 'Duplicate Node',
       type: SdcUiCommon.ModalType.custom,
@@ -98,12 +112,12 @@
     };
   }
 
-  duplicate(node : ITreeNode): void {
-    const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node);
+  duplicate(node: ITreeNode): void {
+    const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node);
     this.existingNames = this.store.getState().service.serviceInstance[this.currentServiceId].existingNames;
-    const toClone  = this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName][this.storeKey];
+    const toClone = this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName][this.storeKey];
     let newObjects = {};
-    for(let i = 0; i < this.numberOfDuplicates; i++) {
+    for (let i = 0; i < this.numberOfDuplicates; i++) {
       const uniqueStoreKey = this.generateUniqueStoreKey(this.currentServiceId, this.currentInstanceId, this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName], newObjects);
       const clone = this.cloneVnf(toClone, this.currentInstanceId);
       newObjects[uniqueStoreKey] = clone;
@@ -114,12 +128,12 @@
   }
 
 
-  cloneVnf(vnf : VnfInstance, originalName: string): VnfInstance {
-    let newUniqueVnf : VnfInstance = _.cloneDeep(vnf);
+  cloneVnf(vnf: VnfInstance, originalName: string): VnfInstance {
+    let newUniqueVnf: VnfInstance = _.cloneDeep(vnf);
 
     newUniqueVnf.originalName = originalName;
     newUniqueVnf.trackById = DefaultDataGeneratorService.createRandomTrackById();
-    if (!_.isNil(vnf.instanceName)){
+    if (!_.isNil(vnf.instanceName)) {
       newUniqueVnf.instanceName = this.ensureUniqueNameOrGenerateOne(vnf.instanceName);
     }
 
@@ -127,10 +141,10 @@
       const vfModuleModel: VfModuleMap = vnf.vfModules[vf_module_model_name];
       for (let vfModule in vfModuleModel) {
         newUniqueVnf.vfModules[vf_module_model_name][vfModule].trackById = DefaultDataGeneratorService.createRandomTrackById();
-        if (!_.isNil(vfModuleModel[vfModule].instanceName)){
+        if (!_.isNil(vfModuleModel[vfModule].instanceName)) {
           newUniqueVnf.vfModules[vf_module_model_name][vfModule].instanceName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].instanceName);
         }
-        if (!_.isNil(vfModuleModel[vfModule].volumeGroupName)){
+        if (!_.isNil(vfModuleModel[vfModule].volumeGroupName)) {
           newUniqueVnf.vfModules[vf_module_model_name][vfModule].volumeGroupName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].volumeGroupName);
         }
       }
@@ -138,7 +152,7 @@
     return newUniqueVnf;
   }
 
-  ensureUniqueNameOrGenerateOne(instanceName){
+  ensureUniqueNameOrGenerateOne(instanceName) {
     let uniqueInstanceName = instanceName;
     if (this.isAlreadyExists(instanceName, this.existingNames)) {
       uniqueInstanceName = this.generateNextUniqueName(instanceName, this.existingNames);
@@ -148,33 +162,33 @@
   }
 
 
-  isAlreadyExists(name : string, existingNames : {[key: string] : any}){
+  isAlreadyExists(name: string, existingNames: { [key: string]: any }) {
     return _.has(existingNames, name.toLowerCase());
   }
 
-  generateNextUniqueName(name : string, existingNames : {[key: string] : any})  :string{
+  generateNextUniqueName(name: string, existingNames: { [key: string]: any }): string {
     let suffix = "000";
     let counter = 1;
-    if (name.match(/^.*_[\d]{3}$/)){
+    if (name.match(/^.*_[\d]{3}$/)) {
       name = name.substring(0, name.length - 4);
     }
 
-    while(true){
-      let paddingNumber : string = this.getNumberAsPaddingString(counter, suffix);
+    while (true) {
+      let paddingNumber: string = this.getNumberAsPaddingString(counter, suffix);
       let candidateUniqueName = name + '_' + paddingNumber;
-      if(!this.isAlreadyExists(candidateUniqueName, existingNames)){
+      if (!this.isAlreadyExists(candidateUniqueName, existingNames)) {
         return candidateUniqueName;
       }
       counter++;
     }
   }
 
-  generateUniqueStoreKey(serviceId : string, objectName : string, existing : any, newObjects: any) : string {
+  generateUniqueStoreKey(serviceId: string, objectName: string, existing: any, newObjects: any): string {
     let counter = 1;
-    while(true){
-      let paddingNumber : string = this.getNumberAsPaddingString(counter, this.padding);
+    while (true) {
+      let paddingNumber: string = this.getNumberAsPaddingString(counter, this.padding);
       const name = objectName + ':' + paddingNumber;
-      if(_.isNil(existing[name]) && _.isNil(newObjects[name])){
+      if (_.isNil(existing[name]) && _.isNil(newObjects[name])) {
         return name;
       }
       counter++;
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts
index 10c1366..089f812 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts
@@ -12,6 +12,7 @@
 import {IframeService} from "../../../../../shared/utils/iframe.service";
 import {DuplicateService} from "../../../duplicate/duplicate.service";
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
+import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 
 class MockAppStore<T> {
   getState() {
@@ -19,27 +20,27 @@
       global: {
         'drawingBoardStatus': DrawingBoardModes.CREATE
       },
-      service : {
-        serviceHierarchy : {
-          'servicedId' : {
-            'networks' : {
-              'networkName' : {
-                'properties' : {
-                  'max_instances' : 1
+      service: {
+        serviceHierarchy: {
+          'servicedId': {
+            'networks': {
+              'networkName': {
+                'properties': {
+                  'max_instances': 1
                 }
               }
             }
           }
         },
-        serviceInstance : {
-          'servicedId' : {
-            'existingNetworksCounterMap' : {
-              'networkId' : 1
+        serviceInstance: {
+          'servicedId': {
+            'existingNetworksCounterMap': {
+              'networkId': 1
             },
-            'networks' : {
-              'networkName' :{
+            'networks': {
+              'networkName': {
                 'action': 'Create',
-                'originalName' : 'networkName'
+                'originalName': 'networkName'
               }
             }
           }
@@ -48,15 +49,24 @@
     }
   }
 }
+
+class MockFeatureFlagsService extends FeatureFlagsService {
+  getAllFlags(): { [p: string]: boolean } {
+    return {};
+  }
+}
+
+
 describe('Network Model Info', () => {
   let injector;
-  let  _dynamicInputsService : DynamicInputsService;
-  let  _sharedTreeService : SharedTreeService;
+  let _dynamicInputsService: DynamicInputsService;
+  let _sharedTreeService: SharedTreeService;
   let networkModel: NetworkModelInfo;
-  let _dialogService : DialogService;
-  let _networkPopupService :  NetworkPopupService;
-  let _duplicateService : DuplicateService;
-  let _iframeService : IframeService;
+  let _dialogService: DialogService;
+  let _networkPopupService: NetworkPopupService;
+  let _duplicateService: DuplicateService;
+  let _iframeService: IframeService;
+  let _featureFlagsService: FeatureFlagsService;
 
   beforeAll(done => (async () => {
     TestBed.configureTestingModule({
@@ -69,13 +79,16 @@
         IframeService,
         DuplicateService,
         {provide: NgRedux, useClass: MockAppStore},
+        {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         MockNgRedux]
     });
     await TestBed.compileComponents();
 
     injector = getTestBed();
     _sharedTreeService = injector.get(SharedTreeService);
-    networkModel = new NetworkModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _networkPopupService, _duplicateService, null, _iframeService, MockNgRedux.getInstance());
+    _featureFlagsService = injector.get(FeatureFlagsService);
+
+    networkModel = new NetworkModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _networkPopupService, _duplicateService, null, _iframeService, _featureFlagsService, MockNgRedux.getInstance());
   })().then(done).catch(done.fail));
 
   test('NetworkModelInfo should be defined', () => {
@@ -137,39 +150,37 @@
     expect(model.type).toEqual('VL');
   });
 
-  test('showNodeIcons should return false if reachLimit of max', ()=>{
-    let serviceId : string = 'servicedId';
+  test('showNodeIcons should return false if reachLimit of max', () => {
+    let serviceId: string = 'servicedId';
     let node = {
-      data : {
-        id : 'networkId',
-        name : 'networkName',
-        modelCustomizationId : 'modelCustomizationId'
+      data: {
+        id: 'networkId',
+        name: 'networkName',
+        modelCustomizationId: 'modelCustomizationId'
       }
     };
     jest.spyOn(_sharedTreeService, 'getExistingInstancesWithDeleteMode').mockReturnValue(0);
     jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({
-      global : {},
-      service : {
-        serviceHierarchy : {
-          'servicedId' : {
-            'networks' : {
-              'networkName' : {
-                'properties' : {
-                  'max_instances' : 1
+      global: {},
+      service: {
+        serviceHierarchy: {
+          'servicedId': {
+            'networks': {
+              'networkName': {
+                'properties': {
+                  'max_instances': 1
                 }
               }
             }
           }
         },
-        serviceInstance : {
-          'servicedId' : {
-            'existingNetworksCounterMap' : {
-              'modelCustomizationId' : 1
+        serviceInstance: {
+          'servicedId': {
+            'existingNetworksCounterMap': {
+              'modelCustomizationId': 1
             },
-            'networks' : {
-              'networkName' :{
-
-              }
+            'networks': {
+              'networkName': {}
             }
           }
         }
@@ -177,41 +188,39 @@
     });
 
     let result = networkModel.showNodeIcons(<any>node, serviceId);
-    expect(result).toEqual(new AvailableNodeIcons(true , false));
+    expect(result).toEqual(new AvailableNodeIcons(true, false));
   });
 
-  test('showNodeIcons should return true if not reachLimit of max', ()=>{
-    let serviceId : string = 'servicedId';
+  test('showNodeIcons should return true if not reachLimit of max', () => {
+    let serviceId: string = 'servicedId';
     let node = {
-      data : {
-        id : 'networkId',
-        name : 'networkName'
+      data: {
+        id: 'networkId',
+        name: 'networkName'
       }
     };
     jest.spyOn(_sharedTreeService, 'getExistingInstancesWithDeleteMode').mockReturnValue(0);
     jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({
-      global : {},
-      service : {
-        serviceHierarchy : {
-          'servicedId' : {
-            'networks' : {
-              'networkName' : {
-                'properties' : {
-                  'max_instances' : 2
+      global: {},
+      service: {
+        serviceHierarchy: {
+          'servicedId': {
+            'networks': {
+              'networkName': {
+                'properties': {
+                  'max_instances': 2
                 }
               }
             }
           }
         },
-        serviceInstance : {
-          'servicedId' : {
-            'existingNetworksCounterMap' : {
-              'networkId' : 1
+        serviceInstance: {
+          'servicedId': {
+            'existingNetworksCounterMap': {
+              'networkId': 1
             },
-            'networks' : {
-              'networkName' :{
-
-              }
+            'networks': {
+              'networkName': {}
             }
           }
         }
@@ -219,34 +228,34 @@
     });
 
     let result = networkModel.showNodeIcons(<any>node, serviceId);
-    expect(result).toEqual(new AvailableNodeIcons(true , false));
+    expect(result).toEqual(new AvailableNodeIcons(true, false));
   });
 
-  test('getNodeCount should return number of nodes', ()=>{
-    let serviceId : string = 'servicedId';
+  test('getNodeCount should return number of nodes', () => {
+    let serviceId: string = 'servicedId';
     jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({
-      global : {},
-      service : {
-        serviceHierarchy : {
-          'servicedId' : {
-            'networks' : {
-              'networkName' : {
-                'properties' : {
-                  'max_instances' : 1
+      global: {},
+      service: {
+        serviceHierarchy: {
+          'servicedId': {
+            'networks': {
+              'networkName': {
+                'properties': {
+                  'max_instances': 1
                 }
               }
             }
           }
         },
-        serviceInstance : {
-          'servicedId' : {
-            'existingNetworksCounterMap' : {
-              'modelCustomizationId' : 1
+        serviceInstance: {
+          'servicedId': {
+            'existingNetworksCounterMap': {
+              'modelCustomizationId': 1
             },
-            'networks' : {
-              'networkName' :{
+            'networks': {
+              'networkName': {
                 'action': 'Create',
-                'originalName' : 'networkName'
+                'originalName': 'networkName'
               }
             }
           }
@@ -255,24 +264,24 @@
     });
 
     let node = {
-      data : {
-        id : 'networkId',
-        name : 'networkName',
+      data: {
+        id: 'networkId',
+        name: 'networkName',
         action: 'Create',
-        modelCustomizationId : "modelCustomizationId",
+        modelCustomizationId: "modelCustomizationId",
         modelUniqueId: "modelCustomizationId"
       }
     };
-    let result = networkModel.getNodeCount(<any>node , serviceId);
+    let result = networkModel.getNodeCount(<any>node, serviceId);
     expect(result).toEqual(1);
 
     node.data.modelCustomizationId = 'networkId_notExist';
     node.data.modelUniqueId = 'networkId_notExist';
-    result = networkModel.getNodeCount(<any>node , serviceId);
+    result = networkModel.getNodeCount(<any>node, serviceId);
     expect(result).toEqual(0);
   });
 
-  test('getMenuAction: showAuditInfoNetwork', ()=>{
+  test('getMenuAction: showAuditInfoNetwork', () => {
 
     jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({
       global: {
@@ -281,7 +290,7 @@
     });
     jest.spyOn(_sharedTreeService, 'isRetryMode').mockReturnValue(true);
     let node = {
-      data : {
+      data: {
         "modelId": "6b528779-44a3-4472-bdff-9cd15ec93450",
         "action": "Create",
         "isFailed": true,
@@ -300,7 +309,7 @@
   test('Info for network should be correct', () => {
     const model = getNetworkModel();
     const instance = getNetworkInstance();
-    let actualNetworkInfo = networkModel.getInfo(model,instance);
+    let actualNetworkInfo = networkModel.getInfo(model, instance);
     let expectedNetworkInfo = [
       ModelInformationItem.createInstance('Network role', "network role 1, network role 2"),
       ModelInformationItem.createInstance("Route target id", null),
@@ -309,26 +318,27 @@
     expect(actualNetworkInfo).toEqual(expectedNetworkInfo);
   });
 
-  function getNetworkModel(){
+  function getNetworkModel() {
     return {
-      "customizationUuid":"94fdd893-4a36-4d70-b16a-ec29c54c184f",
-      "name":"ExtVL",
-      "version":"37.0",
-      "description":"ECOMP generic virtual link (network) base type for all other service-level and global networks",
-      "uuid":"ddc3f20c-08b5-40fd-af72-c6d14636b986",
-      "invariantUuid":"379f816b-a7aa-422f-be30-17114ff50b7c",
-      "max":1,
-      "min":0,
-      "isEcompGeneratedNaming":false,
-      "type":"VL",
-      "modelCustomizationName":"ExtVL 0",
-      "roles":["network role 1"," network role 2"],
-      "properties":{
-        "network_role":"network role 1, network role 2",
+      "customizationUuid": "94fdd893-4a36-4d70-b16a-ec29c54c184f",
+      "name": "ExtVL",
+      "version": "37.0",
+      "description": "ECOMP generic virtual link (network) base type for all other service-level and global networks",
+      "uuid": "ddc3f20c-08b5-40fd-af72-c6d14636b986",
+      "invariantUuid": "379f816b-a7aa-422f-be30-17114ff50b7c",
+      "max": 1,
+      "min": 0,
+      "isEcompGeneratedNaming": false,
+      "type": "VL",
+      "modelCustomizationName": "ExtVL 0",
+      "roles": ["network role 1", " network role 2"],
+      "properties": {
+        "network_role": "network role 1, network role 2",
         "network_assignments":
           "{is_external_network=false, ipv4_subnet_default_assignment={min_subnets_count=1}, ecomp_generated_network_assignment=false, ipv6_subnet_default_assignment={min_subnets_count=1}}",
-        "exVL_naming":"{ecomp_generated_naming=true}","network_flows":"{is_network_policy=false, is_bound_to_vpn=false}",
-        "network_homing":"{ecomp_selected_instance_node_target=false}"
+        "exVL_naming": "{ecomp_generated_naming=true}",
+        "network_flows": "{is_network_policy=false, is_bound_to_vpn=false}",
+        "network_homing": "{ecomp_selected_instance_node_target=false}"
       }
     };
 
@@ -370,9 +380,7 @@
   }
 
 
-
-
-  function getServiceHierarchy(){
+  function getServiceHierarchy() {
     return {
       "service": {
         "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450",
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts
index 3ed40cd..3ba4a2c 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts
@@ -30,6 +30,7 @@
 import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
 import {ComponentInfoType} from "../../../component-info/component-info-model";
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
+import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 
 export class NetworkModelInfo implements ILevelNodeInfo {
   constructor(private _dynamicInputsService: DynamicInputsService,
@@ -39,6 +40,7 @@
               private _duplicateService: DuplicateService,
               private modalService: SdcUiServices.ModalService,
               private _iframeService: IframeService,
+              private _featureFlagsService: FeatureFlagsService,
               private _store: NgRedux<AppState>) {
   }
 
@@ -70,7 +72,7 @@
    ************************************************************/
   getModel = (networkModelId: string, instance: NetworkInstance, serviceHierarchy): NetworkModel => {
     const originalModelName = instance.originalName ? instance.originalName : networkModelId;
-    return new NetworkModel(serviceHierarchy[this.name][originalModelName]);
+    return new NetworkModel(serviceHierarchy[this.name][originalModelName], this._featureFlagsService.getAllFlags());
   };
 
 
@@ -164,8 +166,8 @@
     counter -= this._sharedTreeService.getExistingInstancesWithDeleteMode(node, serviceModelId, 'networks');
 
     const properties = this._store.getState().service.serviceHierarchy[serviceModelId].networks[node.data.name].properties;
-    const maxInstances: number = !_.isNil(properties) ? (properties.max_instances || 1) : 1;
-    const isReachedLimit = !(maxInstances > counter);
+    const flags = FeatureFlagsService.getAllFlags(this._store);
+    const isReachedLimit: boolean = this._sharedTreeService.isReachedToMaxInstances(properties, counter, flags);
     const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !isReachedLimit;
 
     return new AvailableNodeIcons(showAddIcon, isReachedLimit)
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts
index eb9902f..225d84b 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts
@@ -28,6 +28,12 @@
   }
 }
 
+class MockFeatureFlagsService extends  FeatureFlagsService{
+  getAllFlags(): { [p: string]: boolean } {
+    return {};
+  }
+}
+
 describe('VFModule Model Info', () => {
   let injector;
   let  _dynamicInputsService : DynamicInputsService;
@@ -38,6 +44,8 @@
   let _vfModuleUpgradePopupService : VfModuleUpgradePopupService;
   let _iframeService : IframeService;
   let _componentInfoService : ComponentInfoService;
+  let _featureFlagsService : FeatureFlagsService;
+
 
   beforeAll(done => (async () => {
     TestBed.configureTestingModule({
@@ -54,7 +62,7 @@
         AaiService,
         HttpClient,
         HttpHandler,
-        FeatureFlagsService,
+        {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         ComponentInfoService
       ]
     });
@@ -63,7 +71,8 @@
     injector = getTestBed();
     _sharedTreeService = injector.get(SharedTreeService);
     _componentInfoService = injector.get(ComponentInfoService)
-    vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _vfModuleUpgradePopupService, _iframeService, MockNgRedux.getInstance(),_componentInfoService);
+    _featureFlagsService = injector.get(FeatureFlagsService);
+    vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _vfModuleUpgradePopupService, _iframeService,_featureFlagsService,  MockNgRedux.getInstance(),_componentInfoService);
 
   })().then(done).catch(done.fail));
 
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts
index 5e14586..e182b8a 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts
@@ -40,6 +40,7 @@
               private _vfModulePopupService: VfModulePopuopService,
               private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
               private _iframeService: IframeService,
+              private _featureFlagsService: FeatureFlagsService,
               private _store: NgRedux<AppState>,
               private _componentInfoService: ComponentInfoService) {
   }
@@ -306,7 +307,6 @@
       maxNodes = vnfModules[node.data.name].properties.maxCountInstances || 1;
     }
     return !(maxNodes > currentNodeCount);
-
   }
 
   getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } {
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts
index 3af4288..d89280f 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts
@@ -23,6 +23,11 @@
 import {HttpClient, HttpHandler} from "@angular/common/http";
 import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
+class MockFeatureFlagsService extends  FeatureFlagsService{
+  getAllFlags(): { [p: string]: boolean } {
+    return {};
+  }
+}
 
 describe('Vnf Model Info', () => {
  let injector;
@@ -38,6 +43,7 @@
  let _duplicateService : DuplicateService;
  let _iframeService : IframeService;
  let _componentInfoService : ComponentInfoService;
+ let _featureFlagsService : FeatureFlagsService;
 
   let _store : NgRedux<AppState>;
   let vnfModel: VnfModelInfo;
@@ -57,7 +63,7 @@
         AaiService,
         HttpClient,
         HttpHandler,
-        FeatureFlagsService,
+        {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         ComponentInfoService,
         IframeService]
     }).compileComponents();
@@ -65,7 +71,7 @@
     injector = getTestBed();
     _sharedTreeService = injector.get(SharedTreeService);
     _store = injector.get(NgRedux);
-    _componentInfoService = injector.get(ComponentInfoService);
+    _featureFlagsService = injector.get(FeatureFlagsService);
 
     vnfModel = new VnfModelInfo(
       _dynamicInputsService,
@@ -79,6 +85,7 @@
       null,
       _iframeService,
       _componentInfoService,
+      _featureFlagsService,
       _store);
 
 
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts
index 05d4af1..c1255f5 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts
@@ -39,6 +39,7 @@
 import {ComponentInfoService} from "../../../component-info/component-info.service";
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
 import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
+import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 
 export class VnfModelInfo implements ILevelNodeInfo {
   constructor(private _dynamicInputsService: DynamicInputsService,
@@ -47,11 +48,12 @@
               private _dialogService: DialogService,
               private _vnfPopupService: VnfPopupService,
               private _vfModulePopupService: VfModulePopuopService,
-              private _vfModuleUpgradePopupService : VfModuleUpgradePopupService,
+              private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
               private _duplicateService: DuplicateService,
               private modalService: SdcUiServices.ModalService,
               private _iframeService: IframeService,
               private _componentInfoService: ComponentInfoService,
+              private _featureFlagsService: FeatureFlagsService,
               private _store: NgRedux<AppState>) {
   }
 
@@ -87,7 +89,7 @@
    ************************************************************/
   getModel = (vnfModelId: string, instance: VnfInstance, serviceHierarchy): VNFModel => {
     const originalModelName = instance.originalName ? instance.originalName : vnfModelId;
-    return new VNFModel(serviceHierarchy[this.name][originalModelName]);
+    return new VNFModel(serviceHierarchy[this.name][originalModelName], this._featureFlagsService.getAllFlags());
   };
 
 
@@ -104,7 +106,7 @@
     node.typeName = this.typeName;
     node.menuActions = this.getMenuAction(<any>node, model.uuid);
     node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
-    node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage: "";
+    node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
     node = this._sharedTreeService.addingStatusProperty(node);
     return node;
   };
@@ -113,7 +115,7 @@
    * return next level object (VFModule)
    ************************************************************/
   getNextLevelObject = (): VFModuleModelInfo => {
-    return new VFModuleModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._vfModulePopupService, this._vfModuleUpgradePopupService, this._iframeService, this._store, this._componentInfoService);
+    return new VFModuleModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._vfModulePopupService, this._vfModuleUpgradePopupService, this._iframeService, this._featureFlagsService, this._store, this._componentInfoService);
   };
 
   /***********************************************************
@@ -181,8 +183,8 @@
     counter -= this._sharedTreeService.getExistingInstancesWithDeleteMode(node, serviceModelId, 'vnfs');
 
     const properties = this._store.getState().service.serviceHierarchy[serviceModelId].vnfs[node.data.name].properties;
-    const maxInstances: number = !_.isNil(properties) ? (properties.max_instances || 1) : 1;
-    const isReachedLimit = !(maxInstances > counter);
+    const flags = FeatureFlagsService.getAllFlags(this._store);
+    const isReachedLimit: boolean = this._sharedTreeService.isReachedToMaxInstances(properties, counter, flags);
     const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !isReachedLimit;
     return new AvailableNodeIcons(showAddIcon, isReachedLimit)
   }
@@ -211,9 +213,9 @@
       },
       showAuditInfo: {
         method: (node, serviceModelId) => {
-            const instance = this._store.getState().service.serviceInstance[serviceModelId].vnfs[node.data.vnfStoreKey];
-            this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VNF', this);
-          },
+          const instance = this._store.getState().service.serviceInstance[serviceModelId].vnfs[node.data.vnfStoreKey];
+          this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VNF', this);
+        },
         visible: (node) => this._sharedTreeService.shouldShowAuditInfo(node),
         enable: (node) => this._sharedTreeService.shouldShowAuditInfo(node)
       },
@@ -324,8 +326,8 @@
 
   getInfo(model, instance): ModelInformationItem[] {
     const modelInformation = !_.isEmpty(model) ? [
-      ModelInformationItem.createInstance("Min instances",  !_.isNull(model.min)? String(model.min): null),
-      ModelInformationItem.createInstance("Max instances",  !_.isNull(model.max)? String(model.max): null)
+      ModelInformationItem.createInstance("Min instances", !_.isNull(model.min) ? String(model.min) : null),
+      ModelInformationItem.createInstance("Max instances", !_.isNull(model.max) ? String(model.max) : null)
     ] : [];
 
     const instanceInfo = !_.isEmpty(instance) ? [
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts
index 4c779a3..3dbc60a 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts
@@ -26,12 +26,14 @@
   undoDeleteActionVrfInstance
 } from "../../../../../shared/storeUtil/utils/vrf/vrf.actions";
 import * as _ from "lodash";
+import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 
 export class VrfModelInfo implements ILevelNodeInfo {
   constructor(private _store: NgRedux<AppState>,
               private _sharedTreeService: SharedTreeService,
               private _dialogService: DialogService,
               private _iframeService: IframeService,
+              private _featureFlagsService : FeatureFlagsService,
               private _networkStepService: NetworkStepService,
               private _vpnStepService: VpnStepService) {
   }
@@ -70,7 +72,7 @@
       return new VpnModelInfo(this._store, this._sharedTreeService);
     } else {
       if (nextLevelType === 'networks') {
-        return new NetworkModelInfo(null, this._sharedTreeService, null, null, null, null, null, this._store);
+        return new NetworkModelInfo(null, this._sharedTreeService, null, null, null, null, null,this._featureFlagsService,  this._store);
       }
     }
   };
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts
index c101f44..75ae1e1 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts
@@ -3,11 +3,13 @@
 import {ObjectToTreeService} from "../objectToTree.service";
 import * as _ from "lodash";
 import {IModelTreeNodeModel} from "../../../objectsToTree/objectToModelTree/modelTreeNode.model";
+import {FeatureFlagsService} from "../../../../shared/services/featureFlag/feature-flags.service";
 
 @Injectable()
 export class ObjectToModelTreeService {
   numberOfPlusButton: number;
-  constructor(private _objectToTreeService: ObjectToTreeService) {
+
+  constructor(private _objectToTreeService: ObjectToTreeService, private _featureFlagsService: FeatureFlagsService) {
   }
 
   /***********************************************************
@@ -18,9 +20,10 @@
     let _this = this;
     const firstLevelOptions: ILevelNodeInfo[] = _this._objectToTreeService.getFirstLevelOptions();
     let nodes = [];
+    let flags = this._featureFlagsService.getAllFlags();
     for (let option of firstLevelOptions) {
       _.forOwn(serviceModel[option.name], function (item, key) {
-        nodes.push(_this.addFirstLevelModel(serviceModel.service.uuid, key, item, item.type, serviceModel, option));
+        nodes.push(_this.addFirstLevelModel(serviceModel.service.uuid, key, item, item.type, serviceModel, option, flags));
       });
     }
 
@@ -30,10 +33,10 @@
     return nodes;
   }
 
-  calculateNumberOfNodesWithPlusIcon(serviceModel, nodes) : void {
-    this.numberOfPlusButton = nodes.reduce((sum, node)=>{
-      let showNodeIconResult = node.showNodeIcons({data : node}, serviceModel.service.uuid);
-      return (!_.isNil(showNodeIconResult) && showNodeIconResult.addIcon && !showNodeIconResult.vIcon) ?  sum + 1 : sum;
+  calculateNumberOfNodesWithPlusIcon(serviceModel, nodes): void {
+    this.numberOfPlusButton = nodes.reduce((sum, node) => {
+      let showNodeIconResult = node.showNodeIcons({data: node}, serviceModel.service.uuid);
+      return (!_.isNil(showNodeIconResult) && showNodeIconResult.addIcon && !showNodeIconResult.vIcon) ? sum + 1 : sum;
     }, 0);
   }
 
@@ -47,9 +50,9 @@
    * @param parentModel - current parent Model object
    * @param levelNodeInfo - current level node information
    ************************************************************/
-  private addFirstLevelModel(serviceId: string, name, currentModel, type, parentModel, levelNodeInfo: ILevelNodeInfo) {
-    let node = ObjectToModelTreeService.convertItemToTreeNode(serviceId, name, currentModel, type, null, levelNodeInfo);
-    node.children = this.addNextLevelNodes(serviceId, currentModel, parentModel, levelNodeInfo, node);
+  private addFirstLevelModel(serviceId: string, name, currentModel, type, parentModel, levelNodeInfo: ILevelNodeInfo, flags?: { [key: string]: boolean }) {
+    let node = ObjectToModelTreeService.convertItemToTreeNode(serviceId, name, currentModel, type, null, levelNodeInfo, flags);
+    node.children = this.addNextLevelNodes(serviceId, currentModel, parentModel, levelNodeInfo, node, flags);
     return node;
   }
 
@@ -61,13 +64,13 @@
    * @param levelNodeInfo - current level node information
    * @param parentNode - parent node.
    ************************************************************/
-  addNextLevelNodes(serviceId: string, currentModel, parentModel, levelNodeInfo: ILevelNodeInfo, parentNode): any[] {
+  addNextLevelNodes(serviceId: string, currentModel, parentModel, levelNodeInfo: ILevelNodeInfo, parentNode, flags?: { [key: string]: boolean }): any[] {
     if (!_.isNil(levelNodeInfo.childNames) && levelNodeInfo.childNames.length > 0) {
       levelNodeInfo.childNames.forEach(function (childName) {
         if (!_.isNil(currentModel[childName])) {
           let nextLevelNodeInfo = levelNodeInfo.getNextLevelObject.apply(this, [childName]);
           parentNode.children = Object.keys(currentModel[childName]).map((key) =>
-            ObjectToModelTreeService.convertItemToTreeNode(serviceId, key, currentModel[childName][key], childName, currentModel, nextLevelNodeInfo));
+            ObjectToModelTreeService.convertItemToTreeNode(serviceId, key, currentModel[childName][key], childName, currentModel, nextLevelNodeInfo, flags));
         }
       })
     }
@@ -84,17 +87,18 @@
    * @param parentModel - current parent model
    * @param levelNodeInfo - current levelNodeInfo object
    ************************************************************/
-  static convertItemToTreeNode(serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo) {
-    let node : IModelTreeNodeModel = {
+  static convertItemToTreeNode(serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo, flags?: { [key: string]: boolean }) {
+    const type: string = levelNodeInfo.getType();
+    let node: IModelTreeNodeModel = {
       id: currentModel.customizationUuid || currentModel.uuid,
-      modelCustomizationId : currentModel.customizationUuid,
-      modelVersionId:  currentModel.uuid,
-      modelUniqueId : currentModel.customizationUuid || currentModel.uuid,
+      modelCustomizationId: currentModel.customizationUuid,
+      modelVersionId: currentModel.uuid,
+      modelUniqueId: currentModel.customizationUuid || currentModel.uuid,
       name: name,
       tooltip: levelNodeInfo.getTooltip(),
-      type: levelNodeInfo.getType(),
+      type,
       count: currentModel.count || 0,
-      max: currentModel.max || 1,
+      max: ObjectToModelTreeService.getMax(currentModel, type, flags),
       children: [],
       disabled: false,
       dynamicInputs: levelNodeInfo.updateDynamicInputsDataFromModel(currentModel),
@@ -105,15 +109,24 @@
     return node;
   }
 
+  static getMax(currentModel, type, flags: { [key: string]: boolean }) {
+    if (flags && !!flags['FLAG_2002_UNLIMITED_MAX'] && (type === 'VF' || type === 'Network' || type === 'VFmodule')) {
+      return !_.isNil(currentModel.max) ? currentModel.max : null;
+    } else {
+      return currentModel.max || 1
+    }
+  }
 
-  static addExtraFunctionality(node, serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo){
+
+  static addExtraFunctionality(node, serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo) {
     node.onAddClick = (node, serviceId) => levelNodeInfo.onClickAdd(node, serviceId);
     node.getNodeCount = (node, serviceId) => levelNodeInfo.getNodeCount(node, serviceId);
     node.getMenuAction = (node, serviceId) => levelNodeInfo.getMenuAction(node, serviceId);
     node.showNodeIcons = (node, serviceId) => levelNodeInfo.showNodeIcons(node, serviceId);
     node.typeName = levelNodeInfo.typeName;
     node.getModel = levelNodeInfo.getModel.bind(levelNodeInfo);
-    node.getInfo = !_.isNil(levelNodeInfo.getInfo) ? levelNodeInfo.getInfo.bind(levelNodeInfo) : ()=>{};
+    node.getInfo = !_.isNil(levelNodeInfo.getInfo) ? levelNodeInfo.getInfo.bind(levelNodeInfo) : () => {
+    };
     node.componentInfoType = levelNodeInfo.componentInfoType;
     return node;
   }
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts
index 443741f..1e68251 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts
@@ -25,6 +25,7 @@
 import {NetworkStepService} from "./models/vrf/vrfModal/networkStep/network.step.service";
 import {VpnStepService} from "./models/vrf/vrfModal/vpnStep/vpn.step.service";
 import { VfModuleUpgradePopupService } from "../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
+import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
 
 @Injectable()
 export class ObjectToTreeService {
@@ -44,6 +45,7 @@
               private _networkStepService : NetworkStepService,
               private _vpnStepService : VpnStepService,
               private _aaiService : AaiService,
+              private _featureFlagsService: FeatureFlagsService,
               private _store : NgRedux<AppState>) {
   }
 
@@ -54,10 +56,10 @@
    * return all first optional first level of the model tree
    ************************************************************/
   getFirstLevelOptions(): ILevelNodeInfo[] {
-    return [new VnfModelInfo(this._dynamicInputsService, this._sharedTreeService, this._defaultDataGeneratorService, this._dialogService, this._vnfPopupService, this._vfModulePopupService, this._vfModuleUpgradePopupService,this._duplicateService, this._modalService, this._iframeService, this._componentInfoService, this._store)
-      , new NetworkModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._networkPopupService, this._duplicateService, this._modalService, this._iframeService,  this._store),
+    return [new VnfModelInfo(this._dynamicInputsService, this._sharedTreeService, this._defaultDataGeneratorService, this._dialogService, this._vnfPopupService, this._vfModulePopupService, this._vfModuleUpgradePopupService,this._duplicateService, this._modalService, this._iframeService, this._componentInfoService, this._featureFlagsService, this._store)
+      , new NetworkModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._networkPopupService, this._duplicateService, this._modalService, this._iframeService,  this._featureFlagsService, this._store),
       new PnfModelInfo(),
-      new VrfModelInfo(this._store, this._sharedTreeService, this._dialogService, this._iframeService, this._networkStepService, this._vpnStepService),
+      new VrfModelInfo(this._store, this._sharedTreeService, this._dialogService, this._iframeService, this._featureFlagsService, this._networkStepService, this._vpnStepService),
       new CollectionResourceModelInfo(this._store, this._sharedTreeService),
       new ConfigurationModelInfo(this._dynamicInputsService, this._sharedTreeService),
       new VnfGroupingModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._vnfGroupPopupService, this._iframeService, this._aaiService, this._store)];
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts
index c56cc49..b8eddbb 100644
--- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts
@@ -13,6 +13,7 @@
 import {undoUpgradeService, upgradeService} from "../../../shared/storeUtil/utils/service/service.actions";
 import {VNFMethods} from "../../../shared/storeUtil/utils/vnf/vnf.actions";
 import {FeatureFlagsService, Features} from "../../../shared/services/featureFlag/feature-flags.service";
+import {Utils} from "../../../shared/utils/utils";
 
 @Injectable()
 export class SharedTreeService {
@@ -239,6 +240,16 @@
     const mode = this._store.getState().global.drawingBoardStatus;
     return mode === DrawingBoardModes.EDIT || mode=== DrawingBoardModes.CREATE;
   }
+
+
+  isReachedToMaxInstances(properties, counter, flags): boolean{
+    let maxInstances  = Utils.getMaxFirstLevel(properties, flags);
+    if(_.isNil(maxInstances)){
+      return false;
+    }else {
+      return !(maxInstances > counter);
+    }
+  }
   /************************************************
    return number of instances with action Delete
    @type: vnfs networks, vngGroups (not vfModule)