From 1dd5db924b88f390f3301a0e3f229c0a81a91080 Mon Sep 17 00:00:00 2001 From: shrek2000 Date: Thu, 7 Feb 2019 12:57:08 +0200 Subject: Add dependent child service to service Add dependent child service to service Issue-ID: SDC-1987 Change-Id: I5a650f57a27587c4ce6f33059719060ffa1f13de Signed-off-by: shrek2000 --- catalog-be/pom.xml | 6 + .../csar/YamlTemplateParsingHandler.java | 20 +++ .../impl/ComponentInstanceBusinessLogic.java | 139 +++++++++++++++- .../components/impl/NodeFilterUploadCreator.java | 117 ++++++++++++++ .../be/components/impl/ResourceBusinessLogic.java | 12 ++ .../be/components/impl/utils/DirectivesUtils.java | 62 ++++++++ .../sdc/be/components/utils/MapUtils.java | 84 ++++++++++ .../utils/ProxyServicePropertiesUtils.java | 54 +++++++ .../datamodel/utils/UiComponentDataConverter.java | 8 + .../openecomp/sdc/be/impl/ServiceFilterUtils.java | 177 +++++++++++++++++++++ .../sdc/be/servlets/ComponentInstanceServlet.java | 31 ++++ .../openecomp/sdc/be/tosca/ToscaExportHandler.java | 104 +++++++++++- .../sdc/be/tosca/model/ToscaNodeTemplate.java | 40 ++++- .../sdc/be/tosca/utils/NodeFilterConverter.java | 6 +- .../main/resources/config/error-configuration.yaml | 15 ++ .../be/nodeFilter/BaseServiceFilterUtilsTest.java | 73 +++++++++ .../be/nodeFilter/ServiceFilterRenameCiTest.java | 48 ++++++ .../nodeFilter/ServiceFilterUtilsCIChangeTest.java | 89 +++++++++++ .../ServiceFilterUtilsPropertyRemovedTest.java | 38 +++++ .../ServiceFilterUtilsServiceInputTest.java | 56 +++++++ 20 files changed, 1165 insertions(+), 14 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/NodeFilterUploadCreator.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/DirectivesUtils.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/MapUtils.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ProxyServicePropertiesUtils.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/impl/ServiceFilterUtils.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/BaseServiceFilterUtilsTest.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterRenameCiTest.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsCIChangeTest.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsPropertyRemovedTest.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsServiceInputTest.java (limited to 'catalog-be') diff --git a/catalog-be/pom.xml b/catalog-be/pom.xml index 4ebbf82d39..8ab854c3f3 100644 --- a/catalog-be/pom.xml +++ b/catalog-be/pom.xml @@ -36,6 +36,12 @@ ${project.version} compile + + org.onap.sdc.common + onap-tosca-datatype + ${project.version} + compile + diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java index 9bc2d01c6d..48152ea166 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java @@ -10,6 +10,7 @@ import org.apache.commons.lang.StringUtils; import org.openecomp.sdc.be.components.impl.AnnotationBusinessLogic; import org.openecomp.sdc.be.components.impl.GroupTypeBusinessLogic; import org.openecomp.sdc.be.components.impl.ImportUtils; +import org.openecomp.sdc.be.components.impl.NodeFilterUploadCreator; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; @@ -19,6 +20,7 @@ import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.stereotype.Component; import org.yaml.snakeyaml.parser.ParserException; @@ -449,6 +451,8 @@ public class YamlTemplateParsingHandler { setRequirements(nodeTemplateInfo, nodeTemplateJsonMap); setCapabilities(nodeTemplateInfo, nodeTemplateJsonMap); updateProperties(nodeTemplateInfo, nodeTemplateJsonMap); + setDirectives(nodeTemplateInfo, nodeTemplateJsonMap); + setNodeFilter(nodeTemplateInfo, nodeTemplateJsonMap); setSubstitutions(substitutionMappings, nodeTemplateInfo); } else { rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); @@ -514,6 +518,22 @@ public class YamlTemplateParsingHandler { } } + private void setDirectives(UploadComponentInstanceInfo nodeTemplateInfo, + Map nodeTemplateJsonMap) { + List directives = + (List) nodeTemplateJsonMap.get(TypeUtils.ToscaTagNamesEnum.DIRECTIVES.getElementName()); + nodeTemplateInfo.setDirectives(directives); + } + + private void setNodeFilter(UploadComponentInstanceInfo nodeTemplateInfo, + Map nodeTemplateJsonMap) { + if (nodeTemplateJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_FILTER.getElementName())) { + nodeTemplateInfo.setUploadNodeFilterInfo( + new NodeFilterUploadCreator().createNodeFilterData(nodeTemplateJsonMap.get( + TypeUtils.ToscaTagNamesEnum.NODE_FILTER.getElementName()))); + } + } + @SuppressWarnings("unchecked") private Map> createReqModuleFromYaml(Map nodeTemplateJsonMap) { Map> moduleRequirements = new HashMap<>(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index 8c7c47391d..dd8cec347c 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -27,8 +27,10 @@ import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.impl.instance.ComponentInstanceChangeOperationOrchestrator; +import org.openecomp.sdc.be.components.impl.utils.DirectivesUtils; import org.openecomp.sdc.be.components.merge.instance.ComponentInstanceMergeDataBusinessLogic; import org.openecomp.sdc.be.components.merge.instance.DataForMergeHolder; +import org.openecomp.sdc.be.components.utils.ProxyServicePropertiesUtils; import org.openecomp.sdc.be.components.validation.ComponentValidations; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity; @@ -36,6 +38,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; @@ -47,10 +50,12 @@ import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.impl.ForwardingPathUtils; +import org.openecomp.sdc.be.impl.ServiceFilterUtils; import org.openecomp.sdc.be.info.CreateAndAssotiateInfo; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.RequirementDefinition; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; @@ -69,6 +74,7 @@ import org.openecomp.sdc.be.model.ComponentInstanceInput; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames; import org.openecomp.sdc.be.model.jsontitan.operations.ForwardingPathOperation; +import org.openecomp.sdc.be.model.jsontitan.operations.NodeFilterOperation; 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.IComponentInstanceOperation; @@ -136,6 +142,9 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { @Autowired private ForwardingPathOperation forwardingPathOperation; + @Autowired + private NodeFilterOperation serviceFilterOperation; + public ComponentInstanceBusinessLogic() { } @@ -301,7 +310,11 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { filter.setIgnoreCapabiltyProperties(false); filter.setIgnoreComponentInstances(false); filter.setIgnoreRequirements(false); - Either serviceRes = toscaOperationFacade.getToscaElement(resourceInstance.getComponentUid(), filter); + filter.setIgnoreInterfaces(false); + filter.setIgnoreProperties(false); + filter.setIgnoreInputs(false); + Either serviceRes = + toscaOperationFacade.getToscaElement(resourceInstance.getComponentUid(), filter); if (serviceRes.isRight()) { return serviceRes.right().value(); } @@ -311,6 +324,14 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Map> req = service.getRequirements(); resourceInstance.setRequirements(req); + Map serviceInterfaces = service.getInterfaces(); + if(MapUtils.isNotEmpty(serviceInterfaces)) { + serviceInterfaces.forEach(resourceInstance::addInterface); + } + + + resourceInstance.setProperties(ProxyServicePropertiesUtils.getProperties(service)); + String name = service.getNormalizedName() + ToscaOperationFacade.PROXY_SUFFIX; String toscaResourceName = ((Resource) proxyTemplate).getToscaResourceName(); int lastIndexOf = toscaResourceName.lastIndexOf('.'); @@ -718,7 +739,6 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, containerComponentType.getValue(), origInst.getName())); return resultOp; } - listForUpdate.add(updatedCi); } else listForUpdate.add(origInst); @@ -789,8 +809,22 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the name of the component instance {} to {}. A component instance with the same name already exists. ", oldComponentInstance.getName(), newInstanceName); resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, containerComponentType.getValue(), componentInstance.getName())); } + if(!DirectivesUtils.isValid(componentInstance.getDirectives())) { + final String directivesStr = + componentInstance.getDirectives().stream().collect(Collectors.joining(" , ", " [ ", " ] ")); + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, + "Failed to update the directives of the component instance {} to {}. Directives data {} is invalid. ", + oldComponentInstance.getName(), newInstanceName , + directivesStr); + resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.DIRECTIVES_INVALID_VALUE, + directivesStr)); + } } + String newInstanceName = componentInstance.getName(); + String oldInstanceName = null; if (resultOp == null) { + oldComponentInstance = componentInstanceOptional.get(); + newInstanceName = componentInstance.getName(); updateRes = toscaOperationFacade.updateComponentInstanceMetadataOfTopologyTemplate(containerComponent, origComponent, updateComponentInstanceMetadata(oldComponentInstance, componentInstance)); if (updateRes.isRight()) { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update metadata of component instance {} belonging to container component {}. Status is {}. ", componentInstance.getName(), containerComponent.getName(), @@ -802,6 +836,14 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Either result = toscaOperationFacade.cleanAndAddGroupInstancesToComponentInstance(containerComponent, oldComponentInstance, componentInstanceId); if (result.isRight()) CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to rename group instances for container {}. error {} ", componentInstanceId, result.right().value()); + if (containerComponent instanceof Service) { + Either renameEither = + renameServiceFilter((Service) containerComponent, newInstanceName, + oldInstanceName); + if (renameEither.isRight()) { + return renameEither; + } + } } // endregion } @@ -824,6 +866,27 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return resultOp; } + + public Either renameServiceFilter(Service containerComponent, + String newInstanceName, String oldInstanceName) { + + Map renamedNodesFilter = + ServiceFilterUtils.getRenamedNodesFilter((Service) containerComponent, + oldInstanceName, newInstanceName); + for( Entry entry : renamedNodesFilter.entrySet()){ + Either + renameEither = serviceFilterOperation.updateNodeFilter( + containerComponent.getUniqueId(),entry.getKey(),entry.getValue()); + if (renameEither.isRight()){ + return Either.right(componentsUtils.getResponseFormatForResourceInstance( + componentsUtils.convertFromStorageResponse(renameEither.right().value(), ComponentTypeEnum.SERVICE), + containerComponent.getName(), null)); + } + + } + return Either.left(null); + } + /** * @param oldPrefix- * The normalized old vf name @@ -847,6 +910,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { oldComponentInstance.setName(newComponentInstance.getName()); oldComponentInstance.setModificationTime(System.currentTimeMillis()); oldComponentInstance.setCustomizationUUID(UUID.randomUUID().toString()); + oldComponentInstance.setDirectives(newComponentInstance.getDirectives()); if (oldComponentInstance.getGroupInstances() != null) oldComponentInstance.getGroupInstances().forEach(group -> group.setName(getNewGroupName(oldComponentInstance.getNormalizedName(), ValidationUtils.normalizeComponentInstanceName(newComponentInstance.getName()), group.getName()))); return oldComponentInstance; @@ -879,6 +943,23 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Either resultOp = null; try { + if (containerComponent instanceof Service) { + ComponentInstance componentInstance = containerComponent.getComponentInstanceById(componentInstanceId).get(); + Either deleteServiceFilterEither = + serviceFilterOperation.deleteNodeFilter((Service) containerComponent, componentInstanceId); + if (deleteServiceFilterEither.isRight()) { + ActionStatus status = componentsUtils.convertFromStorageResponse(deleteServiceFilterEither.right().value(), + containerComponentType); + titanDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(status, componentInstanceId)); + } + resultOp = deleteServiceFiltersRelatedTobeDeletedComponentInstance((Service) containerComponent, + componentInstance, ComponentTypeEnum.SERVICE, userId); + if (resultOp.isRight()) { + titanDao.rollback(); + return resultOp; + } + } resultOp = deleteComponentInstance(containerComponent, componentInstanceId, containerComponentType); if (resultOp.isRight()){ return resultOp; @@ -895,6 +976,60 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } } + public Either deleteServiceFiltersRelatedTobeDeletedComponentInstance( + Service service, ComponentInstance componentInstance, ComponentTypeEnum containerComponentType, String userId) { + if (containerComponentType.equals(ComponentTypeEnum.SERVICE)) { + Set serviceFiltersIDsToBeDeleted = + getServiceFiltersRelatedToComponentInstance(service.getUniqueId(), componentInstance); + if (!serviceFiltersIDsToBeDeleted.isEmpty()) { + Set ids = service.getComponentInstances().stream() + .filter(ci -> serviceFiltersIDsToBeDeleted + .contains(ci.getName())) + .map(ComponentInstance::getUniqueId) + .collect(Collectors.toSet()); + Either, StorageOperationStatus> deleteServiceFiltersEither = + serviceFilterOperation.deleteNodeFilters(service, ids); + if (deleteServiceFiltersEither.isRight()) { + ActionStatus status = componentsUtils.convertFromStorageResponse(deleteServiceFiltersEither.right().value(), + containerComponentType); + return Either.right(componentsUtils.getResponseFormat(status, componentInstance.getName())); + } + for (String id : ids) { + final Optional componentInstanceById = service.getComponentInstanceById(id); + if (!componentInstanceById.isPresent()){ + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + ComponentInstance ci = componentInstanceById.get(); + List directives = ci.getDirectives(); + directives.remove(DirectivesUtils.SELECTABLE); + ci.setDirectives(directives); + final Either componentInstanceResponseFormatEither = + updateComponentInstanceMetadata(ComponentTypeEnum.SERVICE_PARAM_NAME, service.getUniqueId(), + ci.getUniqueId(), userId, ci, true, false, false); + if (componentInstanceResponseFormatEither.isRight()) { + return componentInstanceResponseFormatEither; + } + } + } + } + return Either.left(componentInstance); + } + + + + private Set getServiceFiltersRelatedToComponentInstance(String containerComponentId, + ComponentInstance componentInstance) { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreComponentInstances(false); + Either serviceFilterOrigin = + toscaOperationFacade.getToscaElement(containerComponentId, filter); + final Service service = serviceFilterOrigin.left().value(); + final Set nodesFiltersToBeDeleted = ServiceFilterUtils.getNodesFiltersToBeDeleted(service, + componentInstance); + return nodesFiltersToBeDeleted; + } + + public Either deleteForwardingPathsRelatedTobeDeletedComponentInstance(String containerComponentId, ComponentTypeEnum containerComponentType, Either resultOp) { if(containerComponentType.equals(ComponentTypeEnum.SERVICE) && resultOp.isLeft() ){ diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/NodeFilterUploadCreator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/NodeFilterUploadCreator.java new file mode 100644 index 0000000000..444ac0b0cf --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/NodeFilterUploadCreator.java @@ -0,0 +1,117 @@ +/* + * Copyright © 2016-2018 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.components.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.onap.sdc.tosca.services.YamlUtil; +import org.openecomp.sdc.be.model.UploadNodeFilterCapabilitiesInfo; +import org.openecomp.sdc.be.model.UploadNodeFilterInfo; +import org.openecomp.sdc.be.model.UploadNodeFilterPropertyInfo; +import org.openecomp.sdc.be.utils.TypeUtils; + +public class NodeFilterUploadCreator { + + + public UploadNodeFilterInfo createNodeFilterData(Object obj) { + if (!(obj instanceof Map)) { + return null; + } + Map nodeFilterMap = (Map) obj; + + UploadNodeFilterInfo uploadNodeFilterInfo = new UploadNodeFilterInfo(); + final String propertiesElementName = TypeUtils.ToscaTagNamesEnum.PROPERTIES.getElementName(); + if (nodeFilterMap.containsKey(propertiesElementName)) { + uploadNodeFilterInfo.setProperties(createNodeFilterProperties(nodeFilterMap.get(propertiesElementName))); + } + final String capabilitiesElementName = TypeUtils.ToscaTagNamesEnum.CAPABILITIES.getElementName(); + if (nodeFilterMap.containsKey(capabilitiesElementName)) { + uploadNodeFilterInfo + .setCapabilities(createNodeFilterCapabilities(nodeFilterMap.get(capabilitiesElementName))); + } + final String toscaId = TypeUtils.ToscaTagNamesEnum.TOSCA_ID.getElementName(); + if (nodeFilterMap.containsKey(toscaId)) { + uploadNodeFilterInfo.setTosca_id(nodeFilterMap.get(toscaId)); + } + return uploadNodeFilterInfo; + } + + private List createNodeFilterProperties(Object o) { + if (!(o instanceof List)) { + return null; + } + List retVal = new ArrayList<>(); + List> propertiesList = (List>) o; + for (Map map : propertiesList) { + final Map.Entry entry = map.entrySet().iterator().next(); + final Object value = entry.getValue(); + if (value instanceof Map) { + List valueList = new ArrayList<>(); + valueList.add(valueToProperty(entry.getValue())); + retVal.add(new UploadNodeFilterPropertyInfo(entry.getKey(), valueList)); + } else if (value instanceof List) { + List propertiesVals = + (List) ((List) value).stream().map(this::valueToProperty).collect(Collectors.toList()); + retVal.add(new UploadNodeFilterPropertyInfo(entry.getKey(), propertiesVals)); + } + } + return retVal; + } + + private String valueToProperty(Object o) { + + if (o instanceof Map) { + return new YamlUtil().objectToYaml(o); + } + return null; + } + + private Map createNodeFilterCapabilities(Object o) { + if (!(o instanceof List)) { + return null; + } + Map retVal = new HashMap<>(); + List> capabilitiesMap = (List>) o; + for (Map map : capabilitiesMap) { + final Map.Entry entry = map.entrySet().iterator().next(); + UploadNodeFilterCapabilitiesInfo uploadNodeFilterCapabilitiesInfo = new UploadNodeFilterCapabilitiesInfo(); + uploadNodeFilterCapabilitiesInfo.setName(entry.getKey()); + uploadNodeFilterCapabilitiesInfo.setProperties(createCapabilitiesProperties(entry.getValue())); + retVal.put(entry.getKey(), uploadNodeFilterCapabilitiesInfo); + } + return retVal; + + } + + private List createCapabilitiesProperties(Object o) { + if (!(o instanceof Map)) { + return null; + } + Map capabilitiesPropertiesMap = (Map) o; + final String capabilitiesPropertiesElementName = TypeUtils.ToscaTagNamesEnum.PROPERTIES.getElementName(); + if (capabilitiesPropertiesMap.containsKey(capabilitiesPropertiesElementName)) { + final Object propertiesObject = capabilitiesPropertiesMap.get(capabilitiesPropertiesElementName); + return createNodeFilterProperties(propertiesObject); + } + return null; + } + + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java index 4e842928ef..d23fcfaa34 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java @@ -34,6 +34,7 @@ import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOpera import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationInfo; import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; +import org.openecomp.sdc.be.components.impl.utils.CINodeFilterUtils; import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic; import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction.LifecycleChanceActionEnum; @@ -3026,6 +3027,17 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ComponentInstance componentInstance = new ComponentInstance(); componentInstance.setComponentUid(refResource.getUniqueId()); + + Collection directives = uploadComponentInstanceInfo.getDirectives(); + if(directives != null && !directives.isEmpty()) { + componentInstance.setDirectives(new ArrayList<>(directives)); + } + UploadNodeFilterInfo uploadNodeFilterInfo = uploadComponentInstanceInfo.getUploadNodeFilterInfo(); + if (uploadNodeFilterInfo != null){ + componentInstance.setNodeFilter(new CINodeFilterUtils().getNodeFilterDataDefinition(uploadNodeFilterInfo, + componentInstance.getUniqueId())); + } + ComponentTypeEnum containerComponentType = resource.getComponentType(); NodeTypeEnum containerNodeType = containerComponentType.getNodeType(); if (containerNodeType.equals(NodeTypeEnum.Resource) diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/DirectivesUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/DirectivesUtils.java new file mode 100644 index 0000000000..b19f0592c1 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/DirectivesUtils.java @@ -0,0 +1,62 @@ +/* + * Copyright © 2016-2018 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.components.impl.utils; + +import com.google.common.collect.Sets; +import java.util.List; +import java.util.Optional; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; + +public class DirectivesUtils { + + public static final String SUBSTITUTABLE = "substitutable"; + public static final String SELECTABLE = "selectable"; + public enum DIRECTIVE { + + SUBSTITUTABLE(DirectivesUtils.SUBSTITUTABLE), SELECTABLE(DirectivesUtils.SELECTABLE); + + private final String value; + + DIRECTIVE(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + + } + + public static Optional getDirective(String inDirective) { + if (StringUtils.isEmpty(inDirective)) { + return Optional.empty(); + } + + return Sets.newHashSet(DIRECTIVE.values()).stream() + .filter(directive -> directive.toString().equals(inDirective)).findAny(); + } + + public static boolean isValid(List inDirectives){ + if (CollectionUtils.isEmpty(inDirectives)){ + return true; + } + return inDirectives.stream().allMatch(directive -> getDirective(directive).isPresent()); + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/MapUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/MapUtils.java new file mode 100644 index 0000000000..30b905789c --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/MapUtils.java @@ -0,0 +1,84 @@ +package org.openecomp.sdc.be.components.utils; + +import java.util.List; +import java.util.Map; + +public class MapUtils { + public static boolean compareMaps(Map source, Map target) { + if (source == null && target == null) { + return true; + } + if ((source == null && target != null) || source != null && target == null + || source.keySet().size() != target.keySet().size()) { + return false; + } + + for (Map.Entry entry : source.entrySet()) { + Object sourceObj = entry.getValue(); + Object targetObj = target.get(entry.getKey()); + if ((sourceObj == null && targetObj != null) || (sourceObj != null && targetObj == null)) { + return false; + } + if (!handleSourceAndTargetObjects(sourceObj, targetObj)) { + return false; + } + } + return true; + + } + + public static boolean compareLists(List source, List target) { + if (source == null && target == null) { + return true; + } + if ((source == null && target != null) || source != null && target == null || + source.size() != target.size()) { + return false; + } + for (int i = 0; i < source.size(); i++) { + Object sourceObj = source.get(i); + Object targetObj = target.get(i); + if ((sourceObj == null && targetObj != null) || sourceObj != null && targetObj == null) { + return false; + } + if (!handleSourceAndTargetObjects(sourceObj, targetObj)) { + return false; + } + } + return true; + } + + public static boolean handleSourceAndTargetObjects(Object sourceObj, Object targetObj) { + + if (sourceObj == null && targetObj == null) { + return true; + } + + if (sourceObj == null && targetObj != null) { + return false; + } + if (sourceObj.getClass().equals(targetObj.getClass())) { + if (sourceObj instanceof Map) { + if (!compareMaps((Map) sourceObj, (Map) targetObj)) { + return false; + } + } else if (sourceObj instanceof List) { + if (!compareLists((List) sourceObj, (List) targetObj)) { + return false; + } + } else { + + if(sourceObj.getClass() != targetObj.getClass()){ + return false; + } + + if (!sourceObj.equals(targetObj)) { + return false; + } + } + } + return true; + } + + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ProxyServicePropertiesUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ProxyServicePropertiesUtils.java new file mode 100644 index 0000000000..b9b7ab690f --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/ProxyServicePropertiesUtils.java @@ -0,0 +1,54 @@ +/* + * Copyright © 2016-2018 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.components.utils; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.PropertyDefinition; + +public class ProxyServicePropertiesUtils { + + private ProxyServicePropertiesUtils() { + } + + public static List getProperties(Component service) { + List properties = service.getProperties(); + if (properties == null) { + properties = new ArrayList<>(); + } + Set serviceProperties = new HashSet<>(properties); + if (service.getInputs() != null) { + Set inputs = service.getInputs().stream().map(input -> new PropertyDefinition(input)) + .collect(Collectors.toSet()); + serviceProperties.addAll(inputs); + } + serviceProperties = + serviceProperties.stream().filter(distinctByKey(PropertyDefinition::getName)).collect(Collectors.toSet()); + return new ArrayList<>(serviceProperties); + } + + public static Predicate distinctByKey(Function keyExtractor) { + Set seen = new HashSet<>(); + return t -> seen.add(keyExtractor.apply(t)); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java index 899a7b1cb8..b76664f968 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java @@ -28,6 +28,7 @@ import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.tosca.utils.NodeFilterConverter; import org.openecomp.sdc.be.ui.model.*; import org.openecomp.sdc.common.log.wrappers.Logger; @@ -101,6 +102,13 @@ public class UiComponentDataConverter { case COMPONENT_INSTANCE_INPUTS: setComponentInstanceInputs(dataTransfer, component); break; + case NODE_FILTER: + if(component.getNodeFilterComponents() == null) { + dataTransfer.setNodeFilterData(null); + } else { + NodeFilterConverter nodeFilterConverter = new NodeFilterConverter(); + dataTransfer.setNodeFilterData(nodeFilterConverter.convertDataMapToUI(component.getNodeFilterComponents())); + } default: break; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ServiceFilterUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ServiceFilterUtils.java new file mode 100644 index 0000000000..7faf89cb89 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ServiceFilterUtils.java @@ -0,0 +1,177 @@ +/* + * Copyright © 2016-2018 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.impl; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.javatuples.Pair; +import org.openecomp.sdc.be.components.impl.utils.DirectivesUtils; +import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.ui.model.UIConstraint; + +public class ServiceFilterUtils { + + + private ServiceFilterUtils() { + } + + + public static boolean isNodeFilterAffectedByPropertyRemoval(Service service, String ciName, String propertyName) { + return service.getComponentInstances().stream().filter(ci -> ci.getNodeFilter() != null) + .anyMatch(ci -> propertyIsUsedInCI(ci, ciName, propertyName)); + } + + + private static boolean propertyIsUsedInCI(ComponentInstance ci, String ciName, String propertyName) { + final List directives = ci.getDirectives(); + if (!directives.contains(DirectivesUtils.SELECTABLE)) { + return false; + } + if (ci.getNodeFilter() == null || ci.getNodeFilter().getProperties() == null + || ci.getNodeFilter().getProperties().getListToscaDataDefinition() == null) { + return false; + } + return ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream() + .flatMap(prop -> prop.getConstraints().stream()).map(String::new) + .filter(constraint -> new ConstraintConvertor().convert(constraint).getSourceType() + .equals(ConstraintConvertor.PROPERTY_CONSTRAINT)) + .anyMatch(constraintStr -> { + UIConstraint uiConstraint = new ConstraintConvertor().convert(constraintStr); + return uiConstraint.getSourceName().equals(ciName) && uiConstraint.getValue().equals(propertyName); + }); + + } + + public static Map getRenamedNodesFilter(Service service, String oldName, + String newName) { + return service.getComponentInstances().stream().filter(ci -> isNodeFilterUsingChangedCi(ci, oldName)) + .map(ci -> renameOldCiNames(ci, oldName, newName)) + .collect(Collectors.toMap(Pair::getValue0, Pair::getValue1)); + } + + private static Pair renameOldCiNames(ComponentInstance ci, String oldName, + String newName) { + ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream() + .filter(property -> isPropertyConstraintChangedByCi(property, oldName)) + .forEach(property -> renamePropertyCiNames(property, oldName, newName)); + + return new Pair<>(ci.getUniqueId(), ci.getNodeFilter()); + } + + private static void renamePropertyCiNames(RequirementNodeFilterPropertyDataDefinition property, String oldName, + String newName) { + final List constraints = property.getConstraints().stream().map(getConstraintString(oldName, newName)) + .collect(Collectors.toList()); + property.setConstraints(constraints); + } + + private static Function getConstraintString(String oldName, String newName) { + return constraint -> { + final ConstraintConvertor constraintConvertor = new ConstraintConvertor(); + UIConstraint uiConstraint = constraintConvertor.convert(constraint); + if (uiConstraint.getSourceName().equals(oldName)) { + uiConstraint.setSourceName(newName); + } + return constraintConvertor.convert(uiConstraint); + }; + } + + + public static Set getNodesFiltersToBeDeleted(Service service, String ciName) { + return service.getComponentInstances().stream().filter(ci -> isNodeFilterUsingChangedCi(ci, ciName)) + .map(ComponentInstance::getName).collect(Collectors.toSet()); + } + + + + public static Set getNodesFiltersToBeDeleted(Service service, ComponentInstance inCi) { + return getNodesFiltersToBeDeleted(service, inCi.getName()); + } + + + + private static boolean isNodeFilterUsingChangedCi(ComponentInstance ci, String name) { + final List directives = ci.getDirectives(); + if (!directives.contains(DirectivesUtils.SELECTABLE)) { + return false; + } + if (ci.getNodeFilter() == null || ci.getNodeFilter().getProperties() == null + || ci.getNodeFilter().getProperties().getListToscaDataDefinition() == null) { + return false; + } + return ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream() + .anyMatch(property -> isPropertyConstraintChangedByCi(property, name)); + } + + private static boolean isPropertyConstraintChangedByCi( + RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition, String name) { + List constraints = requirementNodeFilterPropertyDataDefinition.getConstraints(); + if (constraints == null) { + return false; + } + return constraints.stream().anyMatch(constraint -> isConstraintChangedByCi(constraint, name)); + } + + private static boolean isConstraintChangedByCi(String constraint, String name) { + UIConstraint uiConstraint = new ConstraintConvertor().convert(constraint); + if (uiConstraint == null || uiConstraint.getSourceType() == null) { + return false; + } + if (!uiConstraint.getSourceType().equals(ConstraintConvertor.PROPERTY_CONSTRAINT)) { + return false; + } + return uiConstraint.getSourceName().equals(name); + } + + public static Set getNodesFiltersToBeDeleted(Service service, InputDefinition changedInput) { + return service.getComponentInstances().stream().filter(ci -> isNodeFilterUsingChangedInput(ci, changedInput)) + .map(ComponentInstance::getName).collect(Collectors.toSet()); + } + + private static boolean isNodeFilterUsingChangedInput(ComponentInstance ci, InputDefinition changedInput) { + final List directives = ci.getDirectives(); + if (!directives.contains(DirectivesUtils.SELECTABLE)) { + return false; + } + return ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream() + .anyMatch(property -> isPropertyConstraintChangedByInput(property, changedInput)); + } + + private static boolean isPropertyConstraintChangedByInput( + RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition, + InputDefinition changedInput) { + List constraints = requirementNodeFilterPropertyDataDefinition.getConstraints(); + return constraints.stream().anyMatch(constraint -> isConstraintChangedByInput(constraint, changedInput)); + } + + private static boolean isConstraintChangedByInput(String constraint, InputDefinition changedInput) { + UIConstraint uiConstraint = new ConstraintConvertor().convert(constraint); + if (!uiConstraint.getSourceType().equals(ConstraintConvertor.SERVICE_INPUT_CONSTRAINT)) { + return false; + } + return uiConstraint.getValue().equals(changedInput.getName()); + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java index b5e28148da..45d1c5f589 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java @@ -31,9 +31,12 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; import org.openecomp.sdc.be.components.impl.GroupBusinessLogic; +import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic; +import org.openecomp.sdc.be.components.impl.utils.DirectivesUtils; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.datamodel.ForwardingPaths; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.info.CreateAndAssotiateInfo; @@ -171,6 +174,34 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet { if (actionResponse.isRight()) { return buildErrorResponse(actionResponse.right().value()); } + ComponentInstance resultValue = actionResponse.left().value(); + if (componentTypeEnum.equals(ComponentTypeEnum.SERVICE)){ + boolean shouldCreateServiceFilter = resourceInstance.getDirectives() != null && resourceInstance.getDirectives().contains( + DirectivesUtils.SELECTABLE); + ServiceBusinessLogic + serviceBusinessLogic = (ServiceBusinessLogic) getComponentBL(componentTypeEnum, context); + + if(shouldCreateServiceFilter) { + Either either = + serviceBusinessLogic.createIfNotAlreadyExistServiceFilter(componentId, componentInstanceId, userId, + true); + if (either.isRight()){ + BeEcompErrorManager.getInstance().logBeSystemError("Resource Instance - updateResourceInstance Failed to create service filter."); + log.debug("Failed to create service filter."); + return buildErrorResponse(convertResponse.right().value()); + } + resultValue.setNodeFilter(either.left().value()); + } else { + Either either = serviceBusinessLogic.deleteIfNotAlreadyDeletedServiceFilter(componentId, componentInstanceId, userId,true); + if (either.isRight()){ + BeEcompErrorManager.getInstance().logBeSystemError("Resource Instance - updateResourceInstance Failed to delete service filter."); + log.debug("Failed to delete service filter."); + return buildErrorResponse(convertResponse.right().value()); + } + resultValue.setNodeFilter(null); + } + } + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value()); } catch (Exception e) { 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 06cf2afe36..da0ec1c0ea 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 @@ -29,11 +29,12 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.ImmutableTriple; import org.apache.commons.lang3.tuple.Triple; +import org.onap.sdc.tosca.services.YamlUtil; import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.*; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; @@ -116,6 +117,7 @@ public class ToscaExportHandler { private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}"; private static final List>> DEFAULT_IMPORTS = ConfigurationManager .getConfigurationManager().getConfiguration().getDefaultImports(); + private static YamlUtil yamlUtil = new YamlUtil(); public ToscaExportHandler(){} @@ -587,7 +589,6 @@ public class ToscaExportHandler { } } - private Either convertReqCapAndTypeName(Map componentsCache, Component component, ToscaTemplate toscaNode, Map nodeTypes, ToscaNodeType toscaNodeType, Map dataTypes) { @@ -645,6 +646,8 @@ public class ToscaExportHandler { for (ComponentInstance componentInstance : componentInstances) { ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate(); nodeTemplate.setType(componentInstance.getToscaComponentName()); + nodeTemplate.setDirectives(componentInstance.getDirectives()); + nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter())); Either originComponentRes = capabilityRequirementConverter .getOriginComponent(componentCache, componentInstance); @@ -809,7 +812,6 @@ public class ToscaExportHandler { return interfaces; } - //M3[00001] - NODE TEMPLATE INTERFACES - END private void addComponentInstanceInputs(Map dataTypes, Map> componentInstancesInputs, @@ -1164,6 +1166,102 @@ public class ToscaExportHandler { return Either.left(nodeType); } + + protected NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) { + if (inNodeFilter == null){ + return null; + } + NodeFilter nodeFilter = new NodeFilter(); + + ListDataDefinition origCapabilities = + inNodeFilter.getCapabilities(); + + ListDataDefinition origProperties = inNodeFilter.getProperties(); + + List> capabilitiesCopy = new ArrayList<>(); + List>> propertiesCopy = new ArrayList<>(); + + copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy); + copyNodeFilterProperties(origProperties, propertiesCopy); + + if(CollectionUtils.isNotEmpty(capabilitiesCopy)) { + nodeFilter.setCapabilities(capabilitiesCopy); + } + + if(CollectionUtils.isNotEmpty(propertiesCopy)) { + nodeFilter.setProperties(propertiesCopy); + } + + nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id())); + + + nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class); + + return nodeFilter; + } + + private Object cloneToscaId(Object toscaId) { + return Objects.isNull(toscaId) ? null + : cloneObjectFromYml(toscaId, toscaId.getClass()); + } + + + private Object cloneObjectFromYml(Object objToClone, Class classOfObj) { + String objectAsYml = yamlUtil.objectToYaml(objToClone); + return yamlUtil.yamlToObject(objectAsYml, classOfObj); + } + private void copyNodeFilterCapabilitiesTemplate( + ListDataDefinition origCapabilities, + List> capabilitiesCopy) { + if(origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || + origCapabilities.getListToscaDataDefinition().isEmpty() ) { + return; + } + for(RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) { + Map capabilityFilterCopyMap = new HashMap<>(); + CapabilityFilter capabilityFilter = new CapabilityFilter(); + List>> propertiesCopy = new ArrayList<>(); + copyNodeFilterProperties(capability.getProperties(), propertiesCopy); + capabilityFilter.setProperties(propertiesCopy); + capabilityFilterCopyMap.put(capability.getName(), capabilityFilter); + capabilitiesCopy.add(capabilityFilterCopyMap); + } + } + + private List copyNodeFilterProperty(List propertyList) { + String listAsString = yamlUtil.objectToYaml(propertyList); + return yamlUtil.yamlToObject(listAsString, List.class); + } + + + private void copyNodeFilterProperties( + ListDataDefinition origProperties, + List>> propertiesCopy) { + if(origProperties == null || origProperties.getListToscaDataDefinition() == null || + origProperties.isEmpty()) { + return; + } + for(RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) { + Map> propertyMapCopy = new HashMap<>(); + for(String propertyInfoEntry : propertyDataDefinition.getConstraints()) { + Map propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class); + if (propertyMapCopy.containsKey(propertyDataDefinition.getName())){ + propertyMapCopy.get(propertyDataDefinition.getName()).add(propertyValObj); + } else { + if (propertyDataDefinition.getName() != null) { + List propsList =new ArrayList(); + propsList.add(propertyValObj); + propertyMapCopy.put(propertyDataDefinition.getName(), propsList); + } else { + propertyMapCopy.putAll(propertyValObj); + } + } + } + propertiesCopy.add(propertyMapCopy); + } + + } + private static class CustomRepresenter extends Representer { public CustomRepresenter() { super(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java index b67a2cf233..b17dc3a43f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java @@ -7,9 +7,9 @@ * 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. @@ -25,14 +25,18 @@ import org.apache.commons.collections.MapUtils; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.collections.CollectionUtils; public class ToscaNodeTemplate { + private String type; + private List directives; private ToscaMetadata metadata; private String description; private Map properties; private List> requirements; private Map capabilities; + private NodeFilter node_filter; private Map interfaces; public String getType() { @@ -75,13 +79,33 @@ public class ToscaNodeTemplate { this.metadata = metadata; } - public String getDescription() { - return description; - } + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public List getDirectives() { + return directives; + } + + public void setDirectives(List directives) { + if (CollectionUtils.isEmpty(directives)) { + this.directives = null; + return; + } + this.directives = directives; + } + + public NodeFilter getNode_filter() { + return node_filter; + } - public void setDescription(String description) { - this.description = description; - } + public void setNode_filter(NodeFilter node_filter) { + this.node_filter = node_filter; + } public void setInterfaces( Map interfaces) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/NodeFilterConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/NodeFilterConverter.java index af0837fdcf..8470bd22a0 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/NodeFilterConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/NodeFilterConverter.java @@ -123,6 +123,10 @@ public class NodeFilterConverter { } } + public Map convertDataMapToUI(Map inMap) { + return inMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, o -> convertToUi(o.getValue()))); + } + public UINodeFilter convertToUi(CINodeFilterDataDefinition inNodeFilter) { UINodeFilter retVal = new UINodeFilter(); final ConstraintConvertor constraintConvertor = new ConstraintConvertor(); @@ -131,7 +135,7 @@ public class NodeFilterConverter { } List constraints = inNodeFilter.getProperties().getListToscaDataDefinition().stream() .map(property -> property.getConstraints().iterator().next()) - .map(str -> constraintConvertor.convert(str)) + .map(constraintConvertor::convert) .collect(Collectors.toList()); retVal.setProperties(constraints); return retVal; diff --git a/catalog-be/src/main/resources/config/error-configuration.yaml b/catalog-be/src/main/resources/config/error-configuration.yaml index c92b0fd771..371f77dd89 100644 --- a/catalog-be/src/main/resources/config/error-configuration.yaml +++ b/catalog-be/src/main/resources/config/error-configuration.yaml @@ -2235,6 +2235,21 @@ errors: message: "Error: Property type %1 provided against %2 is not supported for static value.", messageId: "SVC4721" } + + #---------SVC4722------------------------------ + # %1 Directive value set + DIRECTIVES_INVALID_VALUE: { + code: 404, + message: "Error: Invalid directive value : '%1' .", + messageId: "SVC4722" + } +#---------SVC4723----------------------------- +# %1 - Interface Operation output name + INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED: { + code: 400, + message: "Error: Cannot update or delete interface operation output(s) '%1' mapped to an operation input", + messageId: "SVC4723" + } #---------SVC4723----------------------------- # %1 - Interface Operation output name INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED: { diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/BaseServiceFilterUtilsTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/BaseServiceFilterUtilsTest.java new file mode 100644 index 0000000000..7cd7f3f45f --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/BaseServiceFilterUtilsTest.java @@ -0,0 +1,73 @@ +/* + * Copyright © 2016-2018 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.nodeFilter; + +import java.util.Arrays; +import org.junit.Assert; +import org.junit.Before; +import org.openecomp.sdc.be.components.impl.utils.DirectivesUtils; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Service; + +public class BaseServiceFilterUtilsTest { + + protected Service service; + protected RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition; + protected RequirementNodeFilterPropertyDataDefinition requirementNodeFilterPropertyDataDefinition2; + protected static final String CI_NAME = "AAAAAA"; + protected static final String A_PROP_NAME = "A_PROP"; + protected static final String SIZE_PROP = "size"; + protected static final String ORIG_COMP_INSTANCE_ID = "54355645457457"; + + @Before + public void initService() { + try { + service = new Service(); + ComponentInstance componentInstance = new ComponentInstance(); + componentInstance.setUniqueId(CI_NAME); + componentInstance.setName(CI_NAME); + service.setComponentInstances(Arrays.asList(componentInstance)); + componentInstance.setDirectives(Arrays.asList(DirectivesUtils.SELECTABLE)); + CINodeFilterDataDefinition serviceFilter = new CINodeFilterDataDefinition(); + componentInstance.setNodeFilter(serviceFilter); + requirementNodeFilterPropertyDataDefinition = new RequirementNodeFilterPropertyDataDefinition(); + requirementNodeFilterPropertyDataDefinition.setName("Name1"); + requirementNodeFilterPropertyDataDefinition + .setConstraints(Arrays.asList("mem_size:\n" + " equal: { get_property : [" + CI_NAME + ", size]}\n")); + requirementNodeFilterPropertyDataDefinition2 = new RequirementNodeFilterPropertyDataDefinition(); + requirementNodeFilterPropertyDataDefinition2.setName("Name2"); + requirementNodeFilterPropertyDataDefinition2 + .setConstraints(Arrays.asList("mem_size:\n {equal: { get_property : [SELF, "+A_PROP_NAME+"]}}\n")); + + ListDataDefinition listDataDefinition = + new ListDataDefinition<>(Arrays.asList( + requirementNodeFilterPropertyDataDefinition, + requirementNodeFilterPropertyDataDefinition2)); + serviceFilter.setProperties(listDataDefinition); + PropertyDefinition property = new PropertyDefinition(); + property.setName(A_PROP_NAME); + service.setProperties(Arrays.asList(property)); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterRenameCiTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterRenameCiTest.java new file mode 100644 index 0000000000..a6a41c53e9 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterRenameCiTest.java @@ -0,0 +1,48 @@ +/* + * Copyright © 2016-2018 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.nodeFilter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.Map; +import org.junit.Test; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.impl.ServiceFilterUtils; + +public class ServiceFilterRenameCiTest extends BaseServiceFilterUtilsTest { + + protected static final String CI_NEW_NAME = "BBBBB"; + + @Test + public void renameCI() { + Map renamedNodeFilters = getRenamedNodeFilters(CI_NAME, CI_NEW_NAME); + assertNotNull(renamedNodeFilters); + final List constraints = + renamedNodeFilters.get(CI_NAME).getProperties().getListToscaDataDefinition().iterator().next() + .getConstraints(); + assertEquals(1,constraints.size()); + final String constraint = constraints.iterator().next(); + assertTrue(constraint.contains(CI_NEW_NAME)); + } + + private Map getRenamedNodeFilters(String oldName, String newName) { + return ServiceFilterUtils.getRenamedNodesFilter(service, oldName, newName); + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsCIChangeTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsCIChangeTest.java new file mode 100644 index 0000000000..b6bf0ad3b4 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsCIChangeTest.java @@ -0,0 +1,89 @@ +/* + * Copyright © 2016-2018 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.nodeFilter; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import fj.data.Either; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Set; +import org.junit.Test; +import org.mockito.Mockito; +import org.openecomp.sdc.be.auditing.impl.AuditingManager; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ServiceFilterUtils; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.ui.model.UIConstraint; +import org.openecomp.sdc.exception.ResponseFormat; + +public class ServiceFilterUtilsCIChangeTest extends BaseServiceFilterUtilsTest { + + + @Test + public void checkComponentInstanceIsFound() { + Set nodesFiltersToBeDeleted = getNodeFiltersToBeDeleted(CI_NAME); + assertNotNull(nodesFiltersToBeDeleted); + assertTrue(nodesFiltersToBeDeleted.contains(CI_NAME)); + } + + private Set getNodeFiltersToBeDeleted(String inCiName) { + requirementNodeFilterPropertyDataDefinition + .setConstraints(Arrays.asList("mem_size:\n" + " equal:\n" + " get_property: ["+CI_NAME+", some static]\n")); + ComponentInstance ci = new ComponentInstance(); + ci.setName(inCiName); + return ServiceFilterUtils.getNodesFiltersToBeDeleted(service, ci); + } + + @Test + public void checkComponentInstanceIsNotFound() { + Set nodesFiltersToBeDeleted = getNodeFiltersToBeDeleted(CI_NAME + " aaa bbb"); + assertNotNull(nodesFiltersToBeDeleted); + assertTrue(nodesFiltersToBeDeleted.isEmpty()); + assertFalse(nodesFiltersToBeDeleted.contains(CI_NAME)); + } + + @Test + public void testServiceConstraintPairSerialization() throws IOException { + UIConstraint uiConstraint =new UIConstraint(); + ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); + assertTrue(mapper.canSerialize(uiConstraint.getClass())); + String data; + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream() ) { + mapper.writeValue(outputStream, uiConstraint); + data = outputStream.toString(); + + } + assertNotNull(data); + final AuditingManager mock = Mockito.mock(AuditingManager.class); + final Either serviceConstraintPairResponseFormatEither = + new ComponentsUtils(mock) + .convertJsonToObjectUsingObjectMapper(data, new User(), UIConstraint.class, + AuditingActionEnum.ADD_GROUPING, ComponentTypeEnum.SERVICE); + assertTrue(serviceConstraintPairResponseFormatEither.isLeft()); + + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsPropertyRemovedTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsPropertyRemovedTest.java new file mode 100644 index 0000000000..739ba3a9f9 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsPropertyRemovedTest.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2016-2018 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.nodeFilter; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openecomp.sdc.be.impl.ServiceFilterUtils; + +public class ServiceFilterUtilsPropertyRemovedTest extends BaseServiceFilterUtilsTest { + + + @Test + public void checkPropertyIsFound() { + assertTrue(ServiceFilterUtils.isNodeFilterAffectedByPropertyRemoval(service, CI_NAME, SIZE_PROP)); + } + + @Test + public void checkPropertyIsNotFound() { + assertFalse(ServiceFilterUtils.isNodeFilterAffectedByPropertyRemoval(service, CI_NAME, A_PROP_NAME + "XXXX")); + } + +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsServiceInputTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsServiceInputTest.java new file mode 100644 index 0000000000..8f12fd1284 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/nodeFilter/ServiceFilterUtilsServiceInputTest.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2016-2018 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.nodeFilter; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Set; +import org.junit.Test; +import org.openecomp.sdc.be.impl.ServiceFilterUtils; +import org.openecomp.sdc.be.model.InputDefinition; + +public class ServiceFilterUtilsServiceInputTest extends BaseServiceFilterUtilsTest { + + private static final String CONSTRAINT_NAME = "InputName"; + + + @Test + public void checkInputStreamIsFound() { + Set nodesFiltersToBeDeleted = getNodeFiltersToBeDeleted(CONSTRAINT_NAME); + assertNotNull(nodesFiltersToBeDeleted); + assertTrue(nodesFiltersToBeDeleted.contains(CI_NAME)); + } + + private Set getNodeFiltersToBeDeleted(String constraintName) { + requirementNodeFilterPropertyDataDefinition + .setConstraints(Arrays.asList("mem_size:\n equal: {get_input: " + CONSTRAINT_NAME + "}\n")); + InputDefinition inputDefinition = new InputDefinition(); + inputDefinition.setName(constraintName); + return ServiceFilterUtils.getNodesFiltersToBeDeleted(service, inputDefinition); + } + + @Test + public void checkInputStreamIsNOtFound() { + Set nodesFiltersToBeDeleted = getNodeFiltersToBeDeleted(CONSTRAINT_NAME + " aaa bbb"); + assertNotNull(nodesFiltersToBeDeleted); + assertTrue(nodesFiltersToBeDeleted.isEmpty()); + assertFalse(nodesFiltersToBeDeleted.contains(CI_NAME)); + } +} -- cgit 1.2.3-korg