From f3a1aa08a8339ce312013154550c8e8b637f0fc3 Mon Sep 17 00:00:00 2001 From: ojasdubey Date: Thu, 23 May 2019 12:09:35 +0530 Subject: Fix service proxy node type Added properties, interfaces and requirements of the child service to the node type of proxy in the parent cherry picked commit from dublin: e50b5687b62edbafa12bf3825b0441077c5a4820 Change-Id: I2b4bb695c0b3819ada889b144d536b48dd9d1f30 Issue-ID: SDC-2313 Signed-off-by: ojasdubey --- .../be/tosca/CapabilityRequirementConverter.java | 62 +++++++- .../openecomp/sdc/be/tosca/ToscaExportHandler.java | 157 ++++++++++++--------- .../sdc/be/tosca/utils/ToscaExportUtils.java | 109 ++++++++++++++ 3 files changed, 258 insertions(+), 70 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/ToscaExportUtils.java (limited to 'catalog-be/src/main/java/org') diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java index bd797c970b..245eb59301 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java @@ -58,6 +58,7 @@ import static org.apache.commons.lang3.StringUtils.isNoneBlank; public class CapabilityRequirementConverter { private static final String NO_CAPABILITIES = "No Capabilities for node type"; + private static final String NO_REQUIREMENTS = "No Requirements for node type"; private static CapabilityRequirementConverter instance; private static final Logger logger = Logger.getLogger(CapabilityRequirementConverter.class); private static final String PATH_DELIMITER = "."; @@ -84,6 +85,18 @@ public class CapabilityRequirementConverter { return c.getPreviousName(); } + public String buildRequirementNameForComponentInstance(Map componentCache, + ComponentInstance componentInstance, + RequirementDefinition r) { + String prefix = buildCapReqNamePrefix(componentInstance.getNormalizedName()); + if (ComponentUtilities.isNotUpdatedCapReqName(prefix, r.getName(), r.getPreviousName())) { + return buildSubstitutedName(componentCache, r.getName(), r.getPreviousName(), r.getPath(), r.getOwnerId(), + componentInstance).left() + .orValue(r.getName()); + } + return r.getPreviousName(); + } + private String buildCapReqNamePrefix(String normalizedName) { return normalizedName + PATH_DELIMITER; } @@ -187,6 +200,38 @@ public class CapabilityRequirementConverter { return result; } + /** + * Allows to convert requirements of a server proxy node type to tosca template requirements + * @param instanceProxy + * @return converted tosca template requirements + */ + List> convertProxyRequirements(Map componentCache, + ComponentInstance instanceProxy) { + Map> requirements = instanceProxy.getRequirements(); + List> toscaRequirements = new ArrayList<>(); + if (requirements != null) { + requirements.entrySet().stream() + .flatMap(e -> e.getValue().stream()) + .forEach(req -> { + ImmutablePair pair = convertProxyRequirement( + buildRequirementNameForComponentInstance(componentCache, instanceProxy, req), req); + Map requirement = new HashMap<>(); + requirement.put(pair.left, pair.right); + toscaRequirements.add(requirement); + }); + } else { + logger.debug(NO_REQUIREMENTS); + } + + return toscaRequirements; + } + + private ImmutablePair convertProxyRequirement(String requirementName, + RequirementDefinition r) { + ToscaRequirement toscaRequirement = createToscaRequirement(r); + return new ImmutablePair<>(requirementName, toscaRequirement); + } + private List> convertRequirementsAsList(Map componentsCache, Component component) { Map> requirements = component.getRequirements(); List> toscaRequirements = new ArrayList<>(); @@ -202,7 +247,7 @@ public class CapabilityRequirementConverter { logger.debug("Finish convert Requirements for node type"); } } else { - logger.debug("No Requirements for node type"); + logger.debug(NO_REQUIREMENTS); } return toscaRequirements; } @@ -384,6 +429,11 @@ public class CapabilityRequirementConverter { name = buildReqNamePerOwnerByPath(componentsCache, component, r); } logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId()); + ToscaRequirement toscaRequirement = createToscaRequirement(r); + return new ImmutablePair<>(name, toscaRequirement); + } + + private ToscaRequirement createToscaRequirement(RequirementDefinition r) { ToscaRequirement toscaRequirement = new ToscaRequirement(); List occurrences = new ArrayList<>(); @@ -397,8 +447,7 @@ public class CapabilityRequirementConverter { toscaRequirement.setNode(r.getNode()); toscaRequirement.setCapability(r.getCapability()); toscaRequirement.setRelationship(r.getRelationship()); - - return new ImmutablePair<>(name, toscaRequirement); + return toscaRequirement; } /** @@ -424,17 +473,16 @@ public class CapabilityRequirementConverter { /** * Allows to convert capabilities of a server proxy node type to tosca template capabilities - * @param component - * @param proxyComponent * @param instanceProxy * @param dataTypes * @return */ - public Map convertProxyCapabilities(Map componentCache, Component component, Component proxyComponent, ComponentInstance instanceProxy, Map dataTypes) { + public Map convertProxyCapabilities(Map componentCache, + ComponentInstance instanceProxy, + Map dataTypes) { Map> capabilities = instanceProxy.getCapabilities(); Map toscaCapabilities = new HashMap<>(); if (capabilities != null) { - boolean isNodeType = ModelConverter.isAtomicComponent(component); for (Map.Entry> entry : capabilities.entrySet()) { entry.getValue() .stream() diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index 0813650b3a..1301a1c7a9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -45,7 +45,6 @@ import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; -import org.openecomp.sdc.be.model.tosca.ToscaFunctions; import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter; import org.openecomp.sdc.be.tosca.model.*; import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil; @@ -78,6 +77,10 @@ import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import static org.apache.commons.collections.MapUtils.isNotEmpty; import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceDefinitionElement; import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceTypeElement; +import static org.openecomp.sdc.be.tosca.utils.ToscaExportUtils.addInputsToProperties; +import static org.openecomp.sdc.be.tosca.utils.ToscaExportUtils.getProxyNodeTypeInterfaces; +import static org.openecomp.sdc.be.tosca.utils.ToscaExportUtils.getProxyNodeTypeProperties; +import static org.openecomp.sdc.be.tosca.utils.ToscaExportUtils.resolvePropertyDefaultValueFromInput; @org.springframework.stereotype.Component("tosca-export-handler") public class ToscaExportHandler { @@ -223,7 +226,8 @@ public class ToscaExportHandler { } toscaNode = importsRes.left().value().left; Map componentCache = importsRes.left().value().right; - Either, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache , component ); + Either, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, + component); if (nodeTypesMapEither.isRight()) { log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value()); @@ -234,6 +238,16 @@ public class ToscaExportHandler { toscaNode.setNode_types(nodeTypesMap); } + Either, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component); + if (proxyInterfaceTypesEither.isRight()) { + log.debug("Failed to populate service proxy local interface types in tosca, error {}", + nodeTypesMapEither.right().value()); + return Either.right(proxyInterfaceTypesEither.right().value()); + } + Map proxyInterfaceTypes = proxyInterfaceTypesEither.left().value(); + if (MapUtils.isNotEmpty(proxyInterfaceTypes)) { + toscaNode.setInterface_types(proxyInterfaceTypes); + } Either, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll(); if (dataTypesEither.isRight()) { @@ -545,14 +559,11 @@ public class ToscaExportHandler { List inputDef = component.getInputs(); Map mergedProperties = new HashMap<>(); addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent); - if (inputDef != null) { - addInputsToProperties(dataTypes, inputDef, mergedProperties); - } + addInputsToProperties(dataTypes, inputDef, mergedProperties); if(CollectionUtils.isNotEmpty(component.getProperties())) { List properties = component.getProperties(); - Map convertedProperties; - convertedProperties = properties.stream().collect(Collectors.toMap( + Map convertedProperties = properties.stream().collect(Collectors.toMap( PropertyDataDefinition::getName, property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))); @@ -560,9 +571,7 @@ public class ToscaExportHandler { mergedProperties.putAll(convertedProperties); } if (MapUtils.isNotEmpty(mergedProperties)) { - if (Objects.nonNull(inputDef)) { - resolveDefaultPropertyValue(inputDef, mergedProperties, dataTypes); - } + resolvePropertyDefaultValueFromInput(inputDef, mergedProperties, dataTypes); toscaNodeType.setProperties(mergedProperties); } @@ -593,50 +602,6 @@ public class ToscaExportHandler { return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes); } - private void resolveDefaultPropertyValue(List inputDef, - Map mergedProperties, - Map dataTypes) { - for (Map.Entry mergedPropertyEntry : mergedProperties.entrySet()) { - ToscaProperty value = mergedPropertyEntry.getValue(); - if (Objects.nonNull(value) && value.getDefaultp() instanceof Map) { - Map valueAsMap = (Map) value.getDefaultp(); - Object getInputValue = valueAsMap.get(ToscaFunctions.GET_INPUT.getFunctionName()); - if (getInputValue instanceof String) { - String inputName = (String)getInputValue; - Optional matchedInputDefinition = inputDef.stream() - .filter(componentInput -> componentInput.getName().equals(inputName)) - .findFirst(); - if (matchedInputDefinition.isPresent()) { - InputDefinition matchedInput = matchedInputDefinition.get(); - Object resolvedDefaultValue = new PropertyConvertor().convertToToscaObject(matchedInput.getType(), - matchedInput.getDefaultValue(), matchedInput.getSchemaType(), dataTypes, false); - value.setDefaultp(resolvedDefaultValue); - mergedProperties.put(mergedPropertyEntry.getKey(), value); - } - } else if (getInputValue instanceof List) { - // new get_input syntax to refer to sub-element (introduced from TOSCA v1.3) - // e.g. get_input: [input_name, INDEX, inner_property] - // currently resolving default value for the syntax is not supported - log.debug("#resolveDefaultPropertyValue: ignore get_input list syntax. propname={}, val={}", - mergedPropertyEntry.getKey(), getInputValue); - } else { - // Ignore unknown get_input syntax - log.debug("#resolveDefaultPropertyValue: ignore unknown get_input syntax. propname={}, val={}", - mergedPropertyEntry.getKey(), getInputValue); - } - } - } - } - - private void addInputsToProperties(Map dataTypes, - List inputDef, - Map mergedProperties) { - for(InputDefinition input : inputDef) { - ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT); - mergedProperties.put(input.getName(), property); - } - } - private Either convertReqCapAndTypeName(Map componentsCache, Component component, ToscaTemplate toscaNode, Map nodeTypes, ToscaNodeType toscaNodeType, Map dataTypes) { @@ -948,7 +913,59 @@ public class ToscaExportHandler { return toscaNodeType; } - private Either, ToscaError> createProxyNodeTypes(Map componentCache ,Component container ) { + private Either, ToscaError> createProxyInterfaceTypes(Component container) { + + Map proxyInterfaceTypes = new HashMap<>(); + Either, ToscaError> res = Either.left(proxyInterfaceTypes); + List componentInstances = container.getComponentInstances(); + if (CollectionUtils.isEmpty(componentInstances)) { + return res; + } + Map serviceProxyInstanceList = new HashMap<>(); + componentInstances.stream() + .filter(this::isComponentOfTypeServiceProxy) + .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst)); + if (MapUtils.isEmpty(serviceProxyInstanceList)) { + return res; + } + for (Entry entryProxy : serviceProxyInstanceList.entrySet()) { + Component serviceComponent; + ComponentParametersView componentParametersView = new ComponentParametersView(); + componentParametersView.disableAll(); + componentParametersView.setIgnoreInterfaces(false); + Either service = toscaOperationFacade + .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView); + if (service.isRight()) { + log.debug("Failed to fetch original service component with id {} for instance {}", + entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName()); + return Either.right(ToscaError.GENERAL_ERROR); + } else { + serviceComponent = service.left().value(); + } + + Either, StorageOperationStatus> lifecycleTypeEither = + interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(); + if(lifecycleTypeEither.isRight()){ + log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value()); + return Either.right(ToscaError.GENERAL_ERROR); + } + + List allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream() + .map(InterfaceDataDefinition::getType) + .collect(Collectors.toList()); + //Add interface types for local interfaces in the original service component for proxy + Map localInterfaceTypes = addInterfaceTypeElement(serviceComponent, + allGlobalInterfaceTypes); + if (MapUtils.isNotEmpty(localInterfaceTypes)) { + proxyInterfaceTypes.putAll(localInterfaceTypes); + } + + } + return Either.left(proxyInterfaceTypes); + } + + private Either, ToscaError> createProxyNodeTypes(Map componentCache, + Component container) { Map nodeTypesMap = new HashMap<>(); Either, ToscaError> res = Either.left(nodeTypesMap); @@ -971,9 +988,6 @@ public class ToscaExportHandler { if (serviceProxyInstanceList.isEmpty()) { return res; } - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreCapabilities(false); - filter.setIgnoreComponentInstances(false); Either serviceProxyOrigin = toscaOperationFacade .getLatestByName("serviceProxy"); if (serviceProxyOrigin.isRight()) { @@ -988,6 +1002,10 @@ public class ToscaExportHandler { ComponentParametersView componentParametersView = new ComponentParametersView(); componentParametersView.disableAll(); componentParametersView.setIgnoreCategories(false); + componentParametersView.setIgnoreProperties(false); + componentParametersView.setIgnoreInputs(false); + componentParametersView.setIgnoreInterfaces(false); + componentParametersView.setIgnoreRequirements(false); Either service = toscaOperationFacade .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView); if (service.isRight()) { @@ -996,15 +1014,16 @@ public class ToscaExportHandler { serviceComponent = service.left().value(); } - ToscaNodeType toscaNodeType = createProxyNodeType(componentCache , origComponent, serviceComponent, entryProxy.getValue()); + ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent, + entryProxy.getValue()); nodeTypesMap.put(entryProxy.getKey(), toscaNodeType); } return Either.left(nodeTypesMap); } - private ToscaNodeType createProxyNodeType(Map componentCache , Component origComponent, Component proxyComponent, - ComponentInstance instance) { + private ToscaNodeType createProxyNodeType(Map componentCache , Component origComponent, + Component proxyComponent, ComponentInstance instance) { ToscaNodeType toscaNodeType = new ToscaNodeType(); String derivedFrom = ((Resource) origComponent).getToscaResourceName(); @@ -1015,9 +1034,21 @@ public class ToscaExportHandler { } Map dataTypes = dataTypesEither.left().value(); Map capabilities = this.capabilityRequirementConverter - .convertProxyCapabilities( componentCache ,origComponent, proxyComponent, instance, dataTypes); + .convertProxyCapabilities(componentCache, instance, dataTypes); + + if (MapUtils.isNotEmpty(capabilities)) { + toscaNodeType.setCapabilities(capabilities); + } + List> proxyNodeTypeRequirements = this.capabilityRequirementConverter + .convertProxyRequirements(componentCache, instance); + if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) { + toscaNodeType.setRequirements(proxyNodeTypeRequirements); + } + Optional> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes); + proxyProperties.ifPresent(toscaNodeType::setProperties); - toscaNodeType.setCapabilities(capabilities); + Optional> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes); + proxyInterfaces.ifPresent(toscaNodeType::setInterfaces); return toscaNodeType; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/ToscaExportUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/ToscaExportUtils.java new file mode 100644 index 0000000000..20e0698276 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/ToscaExportUtils.java @@ -0,0 +1,109 @@ +/* + * Copyright © 2016-2019 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.tosca.utils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.tosca.ToscaFunctions; +import org.openecomp.sdc.be.tosca.PropertyConvertor; +import org.openecomp.sdc.be.tosca.model.ToscaProperty; + +public class ToscaExportUtils { + + private ToscaExportUtils() { + //Hiding implicit default constructor + } + + public static Optional> getProxyNodeTypeInterfaces(Component proxyComponent, + Map dataTypes) { + if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) { + return Optional.empty(); + } + return Optional.ofNullable(InterfacesOperationsToscaUtil + .getInterfacesMap(proxyComponent, null, proxyComponent.getInterfaces(), dataTypes, false, false)); + } + + public static Optional> getProxyNodeTypeProperties(Component proxyComponent, + Map + dataTypes) { + if (Objects.isNull(proxyComponent)) { + return Optional.empty(); + } + Map proxyProperties = new HashMap<>(); + addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties); + if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) { + proxyProperties.putAll(proxyComponent.getProperties().stream() + .collect(Collectors.toMap(PropertyDataDefinition::getName, + property -> PropertyConvertor.getInstance().convertProperty(dataTypes, property, + PropertyConvertor.PropertyType.PROPERTY)))); + } + resolvePropertyDefaultValueFromInput(proxyComponent.getInputs(), proxyProperties, dataTypes); + + return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty(); + } + + + public static void resolvePropertyDefaultValueFromInput(List componentInputs, + Map mergedProperties, + Map dataTypes) { + if (MapUtils.isEmpty(mergedProperties) || CollectionUtils.isEmpty(componentInputs)) { + return; + } + for (Map.Entry mergedPropertyEntry : mergedProperties.entrySet()) { + ToscaProperty value = mergedPropertyEntry.getValue(); + if (Objects.nonNull(value) && value.getDefaultp() instanceof Map) { + Map valueAsMap = (Map) value.getDefaultp(); + String inputName = valueAsMap.get(ToscaFunctions.GET_INPUT.getFunctionName()); + Optional matchedInputDefinition = componentInputs.stream() + .filter(componentInput -> componentInput.getName().equals(inputName)) + .findFirst(); + if (matchedInputDefinition.isPresent()) { + InputDefinition matchedInput = matchedInputDefinition.get(); + Object resolvedDefaultValue = new PropertyConvertor().convertToToscaObject(matchedInput.getType(), + matchedInput.getDefaultValue(), matchedInput.getSchemaType(), dataTypes, false); + value.setDefaultp(resolvedDefaultValue); + mergedProperties.put(mergedPropertyEntry.getKey(), value); + } + } + } + } + + public static void addInputsToProperties(Map dataTypes, + List componentInputs, + Map mergedProperties) { + if (CollectionUtils.isEmpty(componentInputs)) { + return; + } + for(InputDefinition input : componentInputs) { + ToscaProperty property = new PropertyConvertor().convertProperty(dataTypes, input, + PropertyConvertor.PropertyType.INPUT); + mergedProperties.put(input.getName(), property); + } + } + +} -- cgit 1.2.3-korg