diff options
14 files changed, 554 insertions, 59 deletions
diff --git a/vid-app-common/src/main/java/org/onap/vid/properties/Features.java b/vid-app-common/src/main/java/org/onap/vid/properties/Features.java index 219b65def..939684c58 100644 --- a/vid-app-common/src/main/java/org/onap/vid/properties/Features.java +++ b/vid-app-common/src/main/java/org/onap/vid/properties/Features.java @@ -88,6 +88,7 @@ public enum Features implements Feature { FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY, FLAG_2006_LIMIT_OWNING_ENTITY_SELECTION_BY_ROLES, FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF, + FLAG_EXP_TOPOLOGY_TREE_VFMODULE_NAMES_FROM_OTHER_TOSCA_VERSIONS, ; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java index 579fd09cb..5bfcc5f13 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java @@ -32,8 +32,6 @@ import java.util.stream.Stream; import javax.inject.Inject; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.util.AAITreeConverter; -import org.onap.vid.asdc.AsdcCatalogException; -import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.NodeType; @@ -122,11 +120,13 @@ public class AAIServiceTree { //Populate nodes with model-name & model-version (from aai) aaiTreeNodesEnricher.enrichNodesWithModelVersionAndModelName(nodesAccumulator); - final ServiceModel serviceModel = getServiceModel(aaiTree.getModelVersionId()); + final ServiceModel serviceModel = sdcService.getServiceModelOrThrow(aaiTree.getModelVersionId()); //Populate nodes with model-customization-name (from sdc model) aaiTreeNodesEnricher.enrichNodesWithModelCustomizationName(nodesAccumulator, serviceModel); + aaiTreeNodesEnricher.enrichVfModulesWithModelCustomizationNameFromOtherVersions(nodesAccumulator, aaiTree.getModelInvariantId()); + return aaiTreeConverter.convertTreeToUIModel(aaiTree, globalCustomerId, serviceType, getInstantiationType(serviceModel), getInstanceRole(serviceModel), getInstanceType(serviceModel)); } @@ -163,18 +163,6 @@ public class AAIServiceTree { } } - private ServiceModel getServiceModel(String modelVersionId) { - try { - final ServiceModel serviceModel = sdcService.getService(modelVersionId); - if (serviceModel == null) { - throw new GenericUncheckedException("Model version '" + modelVersionId + "' not found"); - } - return serviceModel; - } catch (AsdcCatalogException e) { - throw new GenericUncheckedException("Exception while loading model version '" + modelVersionId + "'", e); - } - } - public static class AaiRelationship { public final String type; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodesEnricher.java b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodesEnricher.java index e1e35cbec..5956eac20 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodesEnricher.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodesEnricher.java @@ -20,41 +20,58 @@ package org.onap.vid.services; +import static java.util.Collections.emptyMap; import static java.util.stream.Collectors.toSet; +import static org.apache.commons.lang3.StringUtils.isAllEmpty; import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableList; import java.util.Collection; import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.function.Predicate; import javax.inject.Inject; import javax.ws.rs.core.Response; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.AaiClientInterface; +import org.onap.vid.aai.model.ModelVer; import org.onap.vid.asdc.parser.ServiceModelInflator; import org.onap.vid.asdc.parser.ServiceModelInflator.Names; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; +import org.onap.vid.properties.Features; import org.springframework.stereotype.Component; +import org.togglz.core.manager.FeatureManager; @Component public class AAITreeNodesEnricher { private final AaiClientInterface aaiClient; + private final VidService sdcService; + private final ServiceModelInflator serviceModelInflator; + private final FeatureManager featureManager; + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAITreeNodesEnricher.class); @Inject public AAITreeNodesEnricher( AaiClientInterface aaiClient, + VidService sdcService, + FeatureManager featureManager, ServiceModelInflator serviceModelInflator ) { this.aaiClient = aaiClient; + this.sdcService = sdcService; + this.featureManager = featureManager; this.serviceModelInflator = serviceModelInflator; } @@ -70,6 +87,73 @@ public class AAITreeNodesEnricher { }); } + void enrichVfModulesWithModelCustomizationNameFromOtherVersions(Collection<AAITreeNode> nodes, String modelInvariantId) { + if (!featureManager.isActive(Features.FLAG_EXP_TOPOLOGY_TREE_VFMODULE_NAMES_FROM_OTHER_TOSCA_VERSIONS)) { + return; + } + + if (nodes.stream().noneMatch(vfModuleWithMissingData())) { + return; + } + + final List<ModelVer> allModelVersions = aaiClient.getSortedVersionsByInvariantId(modelInvariantId); + + final ListIterator<ModelVer> modelVersionsIterator = allModelVersions.listIterator(); + final Map<String, Names> namesByCustomizationId = new HashMap<>(); + + nodes.stream().filter(vfModuleWithMissingData()).forEach(node -> { + String modelCustomizationId = node.getModelCustomizationId(); + + fetchCustomizationIdsFromToscaModelsWhileNeeded(namesByCustomizationId, modelVersionsIterator, modelCustomizationId); + + final Names names = namesByCustomizationId.get(modelCustomizationId); + if (names != null) { + node.setKeyInModel(names.getModelKey()); + node.setModelCustomizationName(names.getModelCustomizationName()); + } + }); + } + + private Predicate<AAITreeNode> vfModuleWithMissingData() { + final Predicate<AAITreeNode> isVfModule = node -> node.getType() == NodeType.VF_MODULE; + + final Predicate<AAITreeNode> nodeWithMissingData = + node -> isAllEmpty(node.getKeyInModel(), node.getModelCustomizationName()); + + return isVfModule.and(nodeWithMissingData); + } + + /** + * Loads inOutMutableNamesByCustomizationId with all customization IDs from the list of modelVersions. Will seize loading + * if yieldCustomizationId presents in inOutMutableNamesByCustomizationId. + * @param inOutMutableNamesByCustomizationId Mutable Map to fill-up + * @param modelVersions Iterable of model-version-ids to load + * @param yieldCustomizationId The key to stop loading on + */ + void fetchCustomizationIdsFromToscaModelsWhileNeeded( + Map<String, Names> inOutMutableNamesByCustomizationId, + ListIterator<ModelVer> modelVersions, + String yieldCustomizationId + ) { + while (modelVersions.hasNext() && !inOutMutableNamesByCustomizationId.containsKey(yieldCustomizationId)) { + inOutMutableNamesByCustomizationId.putAll( + fetchAllCustomizationIds(modelVersions.next().getModelVersionId()) + ); + } + } + + private Map<String, Names> fetchAllCustomizationIds(String modelVersionId) { + try { + ServiceModel serviceModel = sdcService.getServiceModelOrThrow(modelVersionId); + return serviceModelInflator.toNamesByCustomizationId(serviceModel); + } catch (Exception e) { + // Ignore the failure: SDC may lack the historic model, but this is NOT a reason to fail the whole enrichment + LOGGER.debug(EELFLoggerDelegate.debugLogger, + "Could not get model customization ids from SCD where modelVersionId={}", modelVersionId, e); + return emptyMap(); + } + } + public void enrichNodesWithModelVersionAndModelName(Collection<AAITreeNode> nodes) { Collection<String> invariantIDs = getModelInvariantIds(nodes); diff --git a/vid-app-common/src/main/java/org/onap/vid/services/VidService.java b/vid-app-common/src/main/java/org/onap/vid/services/VidService.java index f7bc1f275..30802f9c6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/VidService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/VidService.java @@ -23,10 +23,13 @@ package org.onap.vid.services; import org.onap.vid.asdc.AsdcCatalogException; import org.onap.vid.model.ServiceModel; +import org.springframework.lang.NonNull; public interface VidService extends ProbeInterface { ServiceModel getService(String uuid) throws AsdcCatalogException; + @NonNull ServiceModel getServiceModelOrThrow(String modelVersionId); + void invalidateServiceCache(); } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java index a5988a156..ef62bf9f6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/VidServiceImpl.java @@ -52,6 +52,7 @@ import org.onap.vid.properties.VidProperties; import org.onap.vid.utils.Logging; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; +import org.springframework.lang.NonNull; import org.togglz.core.manager.FeatureManager; /** @@ -99,11 +100,6 @@ public class VidServiceImpl implements VidService { }); } - /* - * (non-Javadoc) - * - * @see org.onap.vid.controller.VidService#getService(java.lang.String) - */ @Override public ServiceModel getService(String uuid) throws AsdcCatalogException { if (featureManager.isActive(FLAG_SERVICE_MODEL_CACHE)) { @@ -113,6 +109,20 @@ public class VidServiceImpl implements VidService { } } + @NonNull + @Override + public ServiceModel getServiceModelOrThrow(String modelVersionId) { + try { + final ServiceModel serviceModel = getService(modelVersionId); + if (serviceModel == null) { + throw new GenericUncheckedException("Model version '" + modelVersionId + "' not found"); + } + return serviceModel; + } catch (AsdcCatalogException e) { + throw new GenericUncheckedException("Exception while loading model version '" + modelVersionId + "'", e); + } + } + private ServiceModel getServiceFromCache(String uuid) throws AsdcCatalogException { try { return serviceModelCache.get(uuid); diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceIntegrativeTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceIntegrativeTest.java index e447ac71c..934a4711b 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceIntegrativeTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceIntegrativeTest.java @@ -65,7 +65,7 @@ public class AAIServiceIntegrativeTest extends TestWithAaiClient { ExecutorService executorService = MoreExecutors.newDirectExecutorService(); AAIServiceTree aaiServiceTree = new AAIServiceTree( new AAITreeNodeBuilder(aaiClient, logging), - new AAITreeNodesEnricher(aaiClient, null), + new AAITreeNodesEnricher(aaiClient, null, null, null), new AAITreeConverter(new ModelUtil()), null, executorService ); diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeIntegrativeTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeIntegrativeTest.java index 02f127d71..03b5b24cb 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeIntegrativeTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeIntegrativeTest.java @@ -56,6 +56,7 @@ import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.FailureAAITreeNode; import org.onap.vid.model.aaiTree.ServiceInstance; import org.onap.vid.model.aaiTree.Vnf; +import org.onap.vid.properties.Features; import org.onap.vid.testUtils.TestUtils; import org.onap.vid.utils.Logging; import org.springframework.http.HttpMethod; @@ -304,7 +305,10 @@ public class AAIServiceTreeIntegrativeTest { TestUtils.initMockitoMocks(this); reboundLoggingWithMdcMock(); aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClient, logging); - aaiTreeNodesEnricher = new AAITreeNodesEnricher(aaiClient, serviceModelInflator); + aaiTreeNodesEnricher = new AAITreeNodesEnricher(aaiClient, null, featureManager, serviceModelInflator); + + when(featureManager.isActive(Features.FLAG_EXP_TOPOLOGY_TREE_VFMODULE_NAMES_FROM_OTHER_TOSCA_VERSIONS)) + .thenReturn(true); } private void reboundLoggingWithMdcMock() { @@ -320,7 +324,7 @@ public class AAIServiceTreeIntegrativeTest { when(aaiGetVersionByInvariantIdResponse.readEntity(String.class)).thenReturn(getVersionByInvariantIdResponseString); - when(sdcService.getService(any())).thenReturn(mock(ServiceModel.class)); + when(sdcService.getServiceModelOrThrow(any())).thenReturn(mock(ServiceModel.class)); when(serviceModelInflator.toNamesByVersionId(any())).thenReturn(ImmutableMap.of( "11c6dc3e-cd6a-41b3-a50e-b5a10f7157d0", new ServiceModelInflator.Names("vnf-model-customization-name", "vnf-key-in-model") )); @@ -372,11 +376,11 @@ public class AAIServiceTreeIntegrativeTest { when(aaiGetVersionByInvariantIdResponse.readEntity(String.class)). thenReturn(TestUtils.readFileAsString("/getTopology/serviceWithCR/service-design-and-creation.json")); - when(sdcService.getService(any())).thenReturn( + when(sdcService.getServiceModelOrThrow(any())).thenReturn( TestUtils.readJsonResourceFileAsObject("/getTopology/serviceWithCR/serviceWithCRModel.json", ServiceModel.class)); ServiceInstance serviceInstance = new AAIServiceTree(aaiTreeNodeBuilder, - new AAITreeNodesEnricher(aaiClient, new ServiceModelInflator()), aaiTreeConverter, sdcService, executorService) + new AAITreeNodesEnricher(aaiClient, null, featureManager, new ServiceModelInflator()), aaiTreeConverter, sdcService, executorService) .getServiceInstanceTopology("a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", "Emanuel", "a565e6ad-75d1-4493-98f1-33234b5c17e2"); String expected = TestUtils.readFileAsString("/getTopology/serviceWithCR/getTopologyWithCR.json"); @@ -440,7 +444,7 @@ public class AAIServiceTreeIntegrativeTest { when(aaiGetVersionByInvariantIdResponse.readEntity(String.class)).thenReturn(getVersionByInvariantIdResponseString); - when(sdcService.getService(any())).thenReturn(mock(ServiceModel.class)); + when(sdcService.getServiceModelOrThrow(any())).thenReturn(mock(ServiceModel.class)); when(serviceModelInflator.toNamesByVersionId(any())).thenReturn(ImmutableMap.of()); new AAIServiceTree(aaiTreeNodeBuilder, aaiTreeNodesEnricher, aaiTreeConverter, sdcService, executorService) diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodesEnricherTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodesEnricherTest.java index 8aba27932..1766162b5 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodesEnricherTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodesEnricherTest.java @@ -22,27 +22,46 @@ package org.onap.vid.services; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; import static java.util.stream.Collectors.toList; +import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.hamcrest.collection.IsMapContaining.hasKey; +import static org.hamcrest.core.IsNot.not; import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Streams; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import net.javacrumbs.jsonunit.core.Option; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.jetbrains.annotations.NotNull; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.onap.vid.aai.AaiClientInterface; +import org.onap.vid.aai.model.ModelVer; import org.onap.vid.asdc.parser.ServiceModelInflator; import org.onap.vid.asdc.parser.ServiceModelInflator.Names; +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.model.ServiceModel; import org.onap.vid.model.aaiTree.AAITreeNode; -import org.testng.annotations.BeforeTest; +import org.onap.vid.model.aaiTree.NodeType; +import org.onap.vid.properties.Features; +import org.onap.vid.testUtils.TestUtils; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.togglz.core.manager.FeatureManager; @@ -59,9 +78,9 @@ public class AAITreeNodesEnricherTest { @InjectMocks private AAITreeNodesEnricher aaiTreeNodesEnricher; - @BeforeTest + @BeforeMethod public void initMocks() { - MockitoAnnotations.initMocks(this); + TestUtils.initMockitoMocks(this); } private final static String nullString = "null placeholder"; @@ -142,6 +161,192 @@ public class AAITreeNodesEnricherTest { assertThat(toStrings(nodesUnderTest), containsInAnyOrder(toStringsArray(nodesWithVersionIdsAndCustomizationNames(versionIds, expectedNames)))); } + @DataProvider + public static Object[][] enrichVfModulesFilteredOutCases() { + AAITreeNode volumeGroup = new AAITreeNode(); + volumeGroup.setType(NodeType.VOLUME_GROUP); + + AAITreeNode vfModuleWithoutData = new AAITreeNode(); + vfModuleWithoutData.setType(NodeType.VF_MODULE); + + AAITreeNode vfModuleWithModelCustomizationName = new AAITreeNode(); + vfModuleWithModelCustomizationName.setType(NodeType.VF_MODULE); + vfModuleWithModelCustomizationName.setModelCustomizationName("foo"); + + AAITreeNode vfModuleWithKeyInModel = new AAITreeNode(); + vfModuleWithKeyInModel.setType(NodeType.VF_MODULE); + vfModuleWithKeyInModel.setKeyInModel("foo"); + + return new Object[][]{ + {"no nodes", null, true}, + {"no vfmodules", volumeGroup, true}, + {"flag is off", vfModuleWithoutData, false}, + {"all vfmodules with either getKeyInModel or getModelCustomizationId", vfModuleWithModelCustomizationName, true}, + {"all vfmodules with either getKeyInModel or getModelCustomizationId", vfModuleWithKeyInModel, true}, + }; + } + + @Test(dataProvider = "enrichVfModulesFilteredOutCases") + public void enrichVfModulesWithModelCustomizationNameFromOtherVersions_givenFilteredOutCases_doNothing(String reasonToSkip, AAITreeNode node, boolean flagState) { + when(featureManager.isActive(Features.FLAG_EXP_TOPOLOGY_TREE_VFMODULE_NAMES_FROM_OTHER_TOSCA_VERSIONS)) + .thenReturn(flagState); + + when(aaiClient.getSortedVersionsByInvariantId(any())) + .thenThrow(new AssertionError("did not expect reaching getSortedVersionsByInvariantId")); + + List<AAITreeNode> nodes = (node == null) ? emptyList() : ImmutableList.of(node); + aaiTreeNodesEnricher.enrichVfModulesWithModelCustomizationNameFromOtherVersions(nodes, "modelInvariantId"); + } + + @Test + public void enrichVfModulesWithModelCustomizationNameFromOtherVersions_givenMissingKeysFoundInFirstSdcModels_sdcRequestsNotExhausted() { + when(featureManager.isActive(Features.FLAG_EXP_TOPOLOGY_TREE_VFMODULE_NAMES_FROM_OTHER_TOSCA_VERSIONS)) + .thenReturn(true); + + final ListIterator<ModelVer> manyVersionsIterator = manyModelVerIteratorMock(); + + String customizationIdToFind = "please-find-me"; + Names anyNames = mock(Names.class); + + when(serviceModelInflator.toNamesByCustomizationId(any())) + .thenReturn(singletonMap("uuidBefore", anyNames)) + .thenReturn(singletonMap(customizationIdToFind, anyNames)) + .thenReturn(singletonMap("uuidAfter", anyNames)) + ; + + + final Map<String, Names> inOutMutableNamesByCustomizationId = new HashMap<>(); + aaiTreeNodesEnricher.fetchCustomizationIdsFromToscaModelsWhileNeeded( + inOutMutableNamesByCustomizationId, manyVersionsIterator, customizationIdToFind); + + assertThat(inOutMutableNamesByCustomizationId, allOf( + hasKey(customizationIdToFind), + hasKey("uuidBefore"), + not(hasKey("uuidAfter"))) + ); + + verify(manyVersionsIterator, times(2)).next(); + verify(sdcService, times(2)).getServiceModelOrThrow(any()); + } + + private ListIterator<ModelVer> manyModelVerIteratorMock() { + final ModelVer modelVerMock = mock(ModelVer.class); + final ListIterator<ModelVer> result = mock(ListIterator.class); + + when(result.next()).thenReturn(modelVerMock); + when(result.hasNext()) + .thenReturn(true, true, true, true, true, true, false); + + return result; + } + + @FunctionalInterface + public interface Creator<T, R> { + R by(T t); + } + + @Test + public void enrichVfModulesWithModelCustomizationNameFromOtherVersions() { + /* + Verifies the following + + [*] aaiClient.getSortedVersionsByInvariantId response is exhausted + and all models fetched from sdc + -> we can see that model #1 info is populated in nodes + [*] relevant nodes enriched + [*] where data not found: nodes not enriched + [*] where data there already: node left pristine + [*] where node is not vfmodule: node left pristine + + */ + + String modelInvariantId = "modelInvariantId"; + + ///////////// HELPERS + + Creator<Integer, AAITreeNode> nodeMissingData = n -> { + AAITreeNode node = new AAITreeNode(); + node.setType(NodeType.VF_MODULE); + node.setModelCustomizationId("model-customization-id-" + n); + return node; + }; + + Creator<Integer, AAITreeNode> nodeWithData = n -> { + AAITreeNode node = nodeMissingData.by(n); + node.setModelCustomizationName("modelCustomizationName-" + n); + node.setKeyInModel("modelKey-" + n); + return node; + }; + + Creator<Integer, ImmutableMap<String, Names>> namesMap = n -> ImmutableMap.of( + "model-customization-id-" + n, + new Names("modelCustomizationName-" + n, "modelKey-" + n) + ); + + Creator<Integer, ModelVer> modelVer = n -> { + ModelVer m = new ModelVer(); + m.setModelVersion("model-version-" + n); + m.setModelVersionId("model-version-id-" + n); + return m; + }; + + ///////////// SET-UP + + when(featureManager.isActive(Features.FLAG_EXP_TOPOLOGY_TREE_VFMODULE_NAMES_FROM_OTHER_TOSCA_VERSIONS)) + .thenReturn(true); + + /* + +-------------+----------+----------+----------+-----------+-----------+ + | | model v1 | model v2 | model v3 | model v77 | model v99 | + +-------------+----------+----------+----------+-----------+-----------+ + | in AAI list | v | v | v | v | | + | in SDC | v | v | v | | | + | in nodes | v | | v | v | v | + +-------------+----------+----------+----------+-----------+-----------+ + */ + when(aaiClient.getSortedVersionsByInvariantId(modelInvariantId)) + .thenReturn(ImmutableList.of(modelVer.by(3), modelVer.by(77), modelVer.by(2), modelVer.by(1))); + + ServiceModel serviceModel_1 = mock(ServiceModel.class); + when(sdcService.getServiceModelOrThrow("model-version-id-1")).thenReturn(serviceModel_1); + when(serviceModelInflator.toNamesByCustomizationId(serviceModel_1)).thenReturn(namesMap.by(1)); + + ServiceModel serviceModel_2 = mock(ServiceModel.class); + when(sdcService.getServiceModelOrThrow("model-version-id-2")).thenReturn(serviceModel_2); + when(serviceModelInflator.toNamesByCustomizationId(serviceModel_2)).thenReturn(namesMap.by(2)); + + ServiceModel serviceModel_3 = mock(ServiceModel.class); + when(sdcService.getServiceModelOrThrow("model-version-id-3")).thenReturn(serviceModel_3); + when(serviceModelInflator.toNamesByCustomizationId(serviceModel_3)).thenReturn(namesMap.by(3)); + + when(sdcService.getServiceModelOrThrow("model-version-id-77")).thenThrow(GenericUncheckedException.class); + + AAITreeNode nodeWithDataAlready = nodeMissingData.by(1); + nodeWithDataAlready.setModelCustomizationName("significant-customization-name"); + nodeWithDataAlready.setKeyInModel("significant-key-in-model"); + + AAITreeNode nodeNotVfModule = nodeMissingData.by(1); + nodeNotVfModule.setType(NodeType.GENERIC_VNF); + + Collection<AAITreeNode> nodes = ImmutableList.of( + nodeMissingData.by(1), nodeMissingData.by(77), + nodeMissingData.by(3), nodeMissingData.by(99), + nodeWithDataAlready, nodeNotVfModule + ); + + ///////////// TEST + + aaiTreeNodesEnricher.enrichVfModulesWithModelCustomizationNameFromOtherVersions(nodes, modelInvariantId); + + assertThat(nodes, jsonEquals(ImmutableList.of( + nodeWithData.by(1), + nodeWithData.by(3), + nodeMissingData.by(77), // not in sdcService + nodeMissingData.by(99), // not in aaiClient + nodeWithDataAlready, // pristine + nodeNotVfModule // pristine + )).when(Option.IGNORING_ARRAY_ORDER)); + } @NotNull diff --git a/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts index 3b42a1ca1..b9072139e 100644 --- a/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts @@ -215,6 +215,35 @@ describe('A la carte', function () { }); }); + it(`Add ALaCarte vnf where FLAG_2006_LCP_REGIONS_BY_LINE_OF_BUSINESS`, () => { + cy.readFile('cypress/support/jsonBuilders/mocks/jsons/emptyServiceRedux.json').then((res) => { + cy.setTestApiParamToGR(); + res.service.serviceHierarchy['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].service.vidNotions.instantiationType = 'ALaCarte'; + res.service.serviceHierarchy['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].service.inputs = null; + res.global['flags'] = {'FLAG_2006_LCP_REGIONS_BY_LINE_OF_BUSINESS': true}; + cy.setReduxState(<any>res); + cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); + + cy.getElementByDataTestsId('node-2017-488_PASQUALE-vPE 0-add-btn').click({force: true}).then(() => { + cy.selectDropdownOptionByText('productFamily', 'Emanuel'); + cy.selectDropdownOptionByText('lineOfBusiness', 'zzz1'); + cy.selectDropdownOptionByText('lcpRegion', 'foo-name'); + cy.selectDropdownOptionByText('tenant', 'tenantID'); + cy.selectPlatformValue('xxx1'); + cy.getElementByDataTestsId('form-set').click({force: true}).then(() => { + const vnfMenuBtnDataTestId = 'node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0-menu-btn'; + + cy.getElementByDataTestsId(vnfMenuBtnDataTestId).click({force: true}).then(() => { + cy.getElementByDataTestsId('context-menu-edit').click({force: true}) + .getElementByDataTestsId("lineOfBusiness").should('contain', 'zzz1') + .getElementByDataTestsId("lcpRegion").should('contain', 'foo-name') + .getElementByDataTestsId("tenant").should('contain', 'tenantName') + }); + }); + }) + }); + }); + it(`Add ALaCarte VfModule Without LcpRegion Tenant Id And Legacy`, () => { addAlacarteVfmoduleByFlag(true, 'redux-a-la-carte-no-lcp-tenant.json'); }); diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts index 83f722704..4b567328d 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts @@ -16,6 +16,8 @@ import {Constants} from "../../../../utils/constants"; import {CheckboxFormControl} from "../../../../models/formControlModels/checkboxFormControl.model"; import {InputFormControl} from "../../../../models/formControlModels/inputFormControl.model"; import {NodeModel} from "../../../../models/nodeModel"; +import {LcpRegion} from "../../../../models/lcpRegion"; +import {Tenant} from "../../../../models/tenant"; @Injectable() export class SharedControllersService { @@ -25,6 +27,26 @@ export class SharedControllersService { getLineOfBusinessControl = (instance?: any): DropdownFormControl => { + return this.getLineOfBusinessControlInternal(undefined, instance); + }; + + getLineOfBusinessByOwningEntityControl = (instance?: any, serviceId?: string, controls?: FormControlModel[]): DropdownFormControl => { + const service = this._store.getState().service.serviceInstance[serviceId]; + const owningEntityName: string = service.owningEntityName; + + const changeLcpRegionOptionsOnChange = (lineOfBusinessNameParam: string, form: FormGroup) => { + form.controls['lcpCloudRegionId'].enable(); + form.controls['lcpCloudRegionId'].reset(); + this._basicControlGenerator.getSubscribeInitResult( + this._aaiService.getLcpRegionsByOwningEntityAndLineOfBusiness.bind(this, owningEntityName, lineOfBusinessNameParam), + controls.find(item => item.controlName === 'lcpCloudRegionId') as DropdownFormControl, form + ).subscribe() + }; + + return this.getLineOfBusinessControlInternal(changeLcpRegionOptionsOnChange, instance); + }; + + private getLineOfBusinessControlInternal = (onChange: Function, instance?: any): DropdownFormControl => { return new DropdownFormControl({ type: FormControlType.DROPDOWN, controlName: 'lineOfBusiness', @@ -36,6 +58,7 @@ export class SharedControllersService { value: instance ? instance.lineOfBusiness : null, validations: [new ValidatorModel(ValidatorOptions.required, 'is required')], onInitSelectedField: ['lineOfBusinessList'], + onChange, onInit: this._basicControlGenerator.getSubscribeInitResult.bind(null, this._aaiService.getCategoryParameters) }) }; @@ -44,6 +67,20 @@ export class SharedControllersService { const service = this._store.getState().service.serviceInstance[serviceId]; const globalCustomerId: string = service.globalSubscriberId; const serviceType: string = service.subscriptionServiceType; + + const onInit = instance + ? this._basicControlGenerator.getSubscribeInitResult.bind( + this._aaiService, + this._aaiService.getLcpRegionsAndTenants.bind(this, globalCustomerId, serviceType)) + : () => {}; + return this.getTenantControlInternal(onInit, instance); + }; + + getTenantByLcpRegionControl = (serviceId: string, instance?: any): DropdownFormControl => { + return this.getTenantControlInternal(() => {}, instance); + }; + + private getTenantControlInternal = (onInit: Function, instance?: any): DropdownFormControl => { return new DropdownFormControl({ type: FormControlType.DROPDOWN, controlName: 'tenantId', @@ -55,10 +92,7 @@ export class SharedControllersService { onInitSelectedField: instance ? ['lcpRegionsTenantsMap', instance.lcpCloudRegionId] : null, value: instance ? instance.tenantId : null, validations: [new ValidatorModel(ValidatorOptions.required, 'is required')], - onInit: instance ? this._basicControlGenerator.getSubscribeInitResult.bind( - this._aaiService, - this._aaiService.getLcpRegionsAndTenants.bind(this, globalCustomerId, serviceType)) : () => { - } + onInit, }) }; @@ -93,6 +127,70 @@ export class SharedControllersService { const service = this._store.getState().service.serviceInstance[serviceId]; const globalCustomerId: string = service.globalSubscriberId; const serviceType: string = service.subscriptionServiceType; + + const onInit = this._basicControlGenerator.getSubscribeInitResult.bind( + this._aaiService, + this._aaiService.getLcpRegionsAndTenants.bind(this, globalCustomerId, serviceType) + ); + + const changeTenantsOptionsByServiceTypeOnChange = ( + (globalCustomerId, serviceType, lcpCloudRegionIdParam) => { + if (!_.isNil(globalCustomerId) && !_.isNil(serviceType)) { + this._basicControlGenerator.getSubscribeResult.bind(this, + this._aaiService.getLcpRegionsAndTenants(globalCustomerId, serviceType) + .subscribe(res => this.setTenantsOptions(controls, res.lcpRegionsTenantsMap[lcpCloudRegionIdParam]))); + } + + } + ).bind(this, globalCustomerId, serviceType); + + return this.getLcpRegionControlInternal(instance, controls, + false, onInit, ['lcpRegionList'], changeTenantsOptionsByServiceTypeOnChange) + }; + + getLcpRegionByLineOfBusinessControl = (serviceId: string, instance: any, controls: FormControlModel[]): DropdownFormControl => { + const service = this._store.getState().service.serviceInstance[serviceId]; + const owningEntityName: string = service.owningEntityName; + + const changeTenantsOptions = (controls: FormControlModel[], cloudRegionId, lcpRegionList: LcpRegion[]) => { + const lcpRegionOption = (_.isNil(lcpRegionList) || _.isNil(cloudRegionId)) + ? null : lcpRegionList.find(({id}) => id === cloudRegionId); + + if (!_.isNil(lcpRegionOption)) { + this._aaiService.getTenantsByCloudOwnerAndCloudRegionId(lcpRegionOption.cloudOwner, lcpRegionOption.id) + .subscribe(res => this.setTenantsOptions(controls, res)); + } + }; + + const lcpRegionOptionsList = (controls: FormControlModel[]): LcpRegion[] => { + const lcpCloudRegionIdControl = _.isNil(controls) + ? null : controls.find(({controlName}) => controlName === 'lcpCloudRegionId'); + + return _.isNil(lcpCloudRegionIdControl) ? null : lcpCloudRegionIdControl['options$']; + }; + + const loadLcpRegionOptionsOnInit = (_.isNil(instance) || _.isNil(instance.lineOfBusiness)) + ? () => {} + : this._basicControlGenerator.getSubscribeInitResult.bind( + this, () => { + return this._aaiService.getLcpRegionsByOwningEntityAndLineOfBusiness(owningEntityName, instance.lineOfBusiness) + .do(res => changeTenantsOptions(controls, instance.lcpCloudRegionId, res)); + } + ); + + const changeTenantsOptionsByCloudRegionIdOnChange = ( + (controls, lcpCloudRegionIdParam) => changeTenantsOptions(controls, lcpCloudRegionIdParam, lcpRegionOptionsList(controls)) + ).bind(this, controls); + + return this.getLcpRegionControlInternal(instance, controls, + _.isNil(instance) || _.isNil(instance.lineOfBusiness), + loadLcpRegionOptionsOnInit, null, changeTenantsOptionsByCloudRegionIdOnChange + ) + }; + + private getLcpRegionControlInternal = (instance: any, controls: FormControlModel[], isDisabled: boolean, + onInit: Function, onInitSelectedField: string[], changeTenantsOptionsOnChange: Function + ): DropdownFormControl => { return new DropdownFormControl({ type: FormControlType.DROPDOWN, controlName: 'lcpCloudRegionId', @@ -100,26 +198,19 @@ export class SharedControllersService { dataTestId: 'lcpRegion', placeHolder: 'Select LCP Region', name: "lcpRegion", - isDisabled: false, + isDisabled, value: instance ? instance.lcpCloudRegionId : null, validations: [new ValidatorModel(ValidatorOptions.required, 'is required')], - onInitSelectedField: ['lcpRegionList'], - onInit: this._basicControlGenerator.getSubscribeInitResult.bind( - this._aaiService, - this._aaiService.getLcpRegionsAndTenants.bind(this, globalCustomerId, serviceType)), - onChange: (param: string, form: FormGroup) => { + onInitSelectedField, + onInit, + + onChange: (lcpCloudRegionIdParam: string, form: FormGroup) => { form.controls['tenantId'].enable(); form.controls['tenantId'].reset(); - if (!_.isNil(globalCustomerId) && !_.isNil(serviceType)) { - this._basicControlGenerator.getSubscribeResult.bind(this, this._aaiService.getLcpRegionsAndTenants(globalCustomerId, serviceType).subscribe(res => { - controls.find(item => item.controlName === 'tenantId')['options$'] = res.lcpRegionsTenantsMap[param]; - if (res.lcpRegionsTenantsMap[param]) { - controls.find(item => item.controlName === 'tenantId')['hasEmptyOptions'] = res.lcpRegionsTenantsMap[param].length === 0; - } - })); - } - if (Constants.LegacyRegion.MEGA_REGION.indexOf(param) !== -1) { + changeTenantsOptionsOnChange(lcpCloudRegionIdParam); + + if (Constants.LegacyRegion.MEGA_REGION.indexOf(lcpCloudRegionIdParam) !== -1) { form.controls['legacyRegion'].enable(); controls.find(item => item.controlName === 'legacyRegion').isVisible = true; @@ -133,6 +224,12 @@ export class SharedControllersService { }) }; + private setTenantsOptions = (controls: FormControlModel[], tenants: Tenant[]) => { + const tenantsControl = controls.find(item => item.controlName === 'tenantId'); + tenantsControl['options$'] = tenants; + tenantsControl['hasEmptyOptions'] = tenants && tenants.length === 0; + }; + getSDNCControl = (instance: any, extraContents? : object[]): FormControlModel => { return new CheckboxFormControl({ controlName: SDN_C_PRE_LOAD, diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts index 4572fa443..c7d623671 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts @@ -6,7 +6,11 @@ import {ControlGeneratorUtil} from "../control.generator.util.service"; import {AaiService} from "../../../../services/aaiService/aai.service"; import {GenericFormService} from "../../generic-form.service"; import {FormBuilder} from "@angular/forms"; -import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model"; +import { + FormControlModel, + ValidatorModel, + ValidatorOptions +} from "../../../../models/formControlModels/formControl.model"; import {LogService} from "../../../../utils/log/log.service"; import {VnfControlGenerator} from "./vnf.control.generator"; import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; @@ -904,7 +908,9 @@ class MockAppStore<T> { } } -class MockFeatureFlagsService {} +class MockFeatureFlagsService { + getFlagState = () => false; +} describe('VNF Control Generator', () => { let injector; diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts index 169780b29..ef58bc761 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts @@ -4,7 +4,11 @@ import {AaiService} from "../../../../services/aaiService/aai.service"; import {NgRedux} from "@angular-redux/store"; import {HttpClient} from "@angular/common/http"; import {ControlGeneratorUtil} from "../control.generator.util.service"; -import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model"; +import { + FormControlModel, + ValidatorModel, + ValidatorOptions +} from "../../../../models/formControlModels/formControl.model"; import {LogService} from "../../../../utils/log/log.service"; import {VNFModel} from "../../../../models/vnfModel"; import {AppState} from "../../../../store/reducers"; @@ -14,6 +18,7 @@ import * as _ from 'lodash'; import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; import {MultiSelectItem} from "../../../formControls/component/multiselect/multiselect.model"; import {SharedControllersService} from "../sharedControlles/shared.controllers.service"; +import {FeatureFlagsService, Features} from "../../../../services/featureFlag/feature-flags.service"; @Injectable() export class VnfControlGenerator { @@ -21,6 +26,7 @@ export class VnfControlGenerator { constructor(private genericFormService: GenericFormService, private _basicControlGenerator: ControlGeneratorUtil, private _sharedControllersService : SharedControllersService, + private _featureFlagsService: FeatureFlagsService, private store: NgRedux<AppState>, private http: HttpClient, private _aaiService: AaiService, @@ -72,14 +78,28 @@ export class VnfControlGenerator { const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfName]); if (!_.isNil(vnfModel)) { - const flags = this.store.getState().global.flags; + const isMultiSelected = + this._featureFlagsService.getFlagState(Features.FLAG_2002_VNF_PLATFORM_MULTI_SELECT); + const lcpRegionsByLineOFBusiness = + this._featureFlagsService.getFlagState(Features.FLAG_2006_LCP_REGIONS_BY_LINE_OF_BUSINESS); + result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming)); result.push(this._sharedControllersService.getProductFamilyControl(vnfInstance, result, true)); - result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vnfInstance, result)); - result.push(this._sharedControllersService.getLegacyRegion(vnfInstance)); - result.push(this._sharedControllersService.getTenantControl(serviceId, vnfInstance)); - result.push(this.getPlatformMultiselectControl(vnfInstance, result, flags['FLAG_2002_VNF_PLATFORM_MULTI_SELECT'])); - result.push(this._sharedControllersService.getLineOfBusinessControl(vnfInstance)); + + if (lcpRegionsByLineOFBusiness) { + result.push(this._sharedControllersService.getLineOfBusinessByOwningEntityControl(vnfInstance, serviceId, result)); + result.push(this._sharedControllersService.getLcpRegionByLineOfBusinessControl(serviceId, vnfInstance, result)); + result.push(this._sharedControllersService.getLegacyRegion(vnfInstance)); + result.push(this._sharedControllersService.getTenantByLcpRegionControl(serviceId, vnfInstance)); + result.push(this.getPlatformMultiselectControl(vnfInstance, result, isMultiSelected)); + } else { + result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vnfInstance, result)); + result.push(this._sharedControllersService.getLegacyRegion(vnfInstance)); + result.push(this._sharedControllersService.getTenantControl(serviceId, vnfInstance)); + result.push(this.getPlatformMultiselectControl(vnfInstance, result, isMultiSelected)); + result.push(this._sharedControllersService.getLineOfBusinessControl(vnfInstance)); + } + result.push(this._sharedControllersService.getRollbackOnFailureControl(vnfInstance)); } return result; diff --git a/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts b/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts index 9026a5648..603ba814d 100644 --- a/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts +++ b/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts @@ -29,7 +29,14 @@ import {VnfInstance} from "../../models/vnfInstance"; import {VfModuleInstance} from "../../models/vfModuleInstance"; import {ServiceInstance} from "../../models/serviceInstance"; import {VfModuleMap} from "../../models/vfModulesMap"; -import {updateAicZones, updateCategoryParameters, updateLcpRegionsAndTenants, updateServiceTypes, updateSubscribers, updateUserId} from "../../storeUtil/utils/general/general.actions"; +import { + updateAicZones, + updateCategoryParameters, + updateLcpRegionsAndTenants, + updateServiceTypes, + updateSubscribers, + updateUserId +} from "../../storeUtil/utils/general/general.actions"; import {createServiceInstance, updateModel,} from "../../storeUtil/utils/service/service.actions"; import {FeatureFlagsService, Features} from "../featureFlag/feature-flags.service"; import {VnfMember} from "../../models/VnfMember"; @@ -221,6 +228,45 @@ export class AaiService { cloudRegionId+AaiService.formatCloudOwnerTrailer(cloudOwner) : cloudRegionId; }; + + + + + getLcpRegionsByOwningEntityAndLineOfBusiness = (owningEntityName, lineOfBusinessName): Observable<LcpRegion[]> => { + // let pathQuery: string = Constants.Path.AAI_GET_LCP_REGIONS_BY____ + // + "?" + // + "owningEntityName=" + owningEntityName + // + "lineOfBusinessName=" + lineOfBusinessName; + + return of([ + new LcpRegion("foo-id", "foo-name", true, "foo-cloud-owner"), + new LcpRegion("foo2-id", "foo2-name", true, "foo2-cloud-owner"), + ]); + }; + + + getTenantsByCloudOwnerAndCloudRegionId = (cloudOwner, cloudRegionId): Observable<Tenant[]> => { + // let pathQuery: string = Constants.Path.AAI_GET_TENANTS_BY____ + // + "?" + // + "cloudOwner=" + cloudOwner + // + "&cloudRegionId=" + cloudRegionId; + + return of([ + new Tenant({ + tenantID: "tenantID", tenantName: "tenantName", + cloudOwner: "cloudOwner", ['is-permitted']: true, + }), + new Tenant({ + tenantID: "tenant2ID", tenantName: "tenant2Name", + cloudOwner: "cloudOwner", ['is-permitted']: true, + }), + ]) + }; + + + + + public static formatCloudOwnerTrailer(cloudOwner: string):string { return " ("+ cloudOwner.trim().toLowerCase().replace(/^[^-]*-/, "").toUpperCase() + ")"; } diff --git a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts index 5842662fb..2c30d9385 100644 --- a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts +++ b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts @@ -13,12 +13,14 @@ export enum Features { FLAG_FLASH_REPLACE_VF_MODULE ='FLAG_FLASH_REPLACE_VF_MODULE', FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT ='FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT', FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS ='FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS', + FLAG_2002_VNF_PLATFORM_MULTI_SELECT= 'FLAG_2002_VNF_PLATFORM_MULTI_SELECT', FLAG_2004_INSTANTIATION_STATUS_FILTER ='FLAG_2004_INSTANTIATION_STATUS_FILTER', FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE = 'FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE', FLAG_2006_VFM_SDNC_PRELOAD_FILES = 'FLAG_2006_VFM_SDNC_PRELOAD_FILES', FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO = 'FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO', FLAG_2004_INSTANTIATION_TEMPLATES_POPUP = 'FLAG_2004_INSTANTIATION_TEMPLATES_POPUP', FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY= 'FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY', + FLAG_2006_LCP_REGIONS_BY_LINE_OF_BUSINESS = 'FLAG_2006_LCP_REGIONS_BY_LINE_OF_BUSINESS', FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF = 'FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF', } |