From 7be04e3e3bdc899c52ffea1f6e11731771903f93 Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Mon, 25 Jul 2022 10:41:31 +0100 Subject: Centralize TOSCA function validation The validation happening in the component instance properties, should also be applied for the Group instance properties and Policy instance properties. Fixes some other problems related to the TOSCA function. Change-Id: I4b69da57a8444b78c72561f49146d32c6911482e Issue-ID: SDC-4114 Signed-off-by: andre.schmid --- .../sdc/be/components/impl/BaseBusinessLogic.java | 23 - .../impl/ComponentInstanceBusinessLogic.java | 13 +- .../sdc/be/components/impl/GroupBusinessLogic.java | 60 +-- .../be/components/impl/GroupBusinessLogicNew.java | 9 +- .../be/components/impl/PolicyBusinessLogic.java | 39 +- .../validation/ToscaFunctionValidatorImpl.java | 206 +++++++++ .../sdc/config/CatalogBESpringConfig.java | 1 + .../impl/ComponentInstanceBusinessLogicTest.java | 512 +-------------------- .../be/components/impl/GroupBusinessLogicTest.java | 14 +- .../components/impl/PolicyBusinessLogicTest.java | 19 +- .../impl/ResourceInstanceBusinessLogicTest.java | 148 +++--- .../validation/ToscaFunctionValidatorImplTest.java | 498 ++++++++++++++++++++ .../sdc/be/servlets/GroupEndpointTest.java | 15 +- 13 files changed, 886 insertions(+), 671 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/validation/ToscaFunctionValidatorImpl.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/validation/ToscaFunctionValidatorImplTest.java (limited to 'catalog-be') diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java index a1f28299a1..1f6d2a4601 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java @@ -336,29 +336,6 @@ public abstract class BaseBusinessLogic { return cmpt; } - String updateInputPropertyObjectValue(T property) { - String propertyType = property.getType(); - String innerType = getInnerType(property); - // Specific Update Logic - Either isValid = propertyOperation - .validateAndUpdatePropertyValue(propertyType, property.getValue(), true, innerType, - componentsUtils.getAllDataTypes(applicationDataTypeCache, property.getModel())); - String newValue = property.getValue(); - if (isValid.isRight()) { - Boolean res = isValid.right().value(); - if (Boolean.FALSE.equals(res)) { - throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse( - DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT))); - } - } else { - Object object = isValid.left().value(); - if (object != null) { - newValue = object.toString(); - } - } - return newValue; - } - String getInnerType(T property) { ToscaPropertyType type = ToscaPropertyType.isValidType(property.getType()); log.debug("#getInnerType - The type of the property {} is {}", property.getUniqueId(), property.getType()); 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 76db103525..577c49106c 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 @@ -48,7 +48,6 @@ import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; -import org.openecomp.sdc.be.components.impl.exceptions.ToscaFunctionExceptionSupplier; import org.openecomp.sdc.be.components.impl.exceptions.ToscaGetFunctionExceptionSupplier; import org.openecomp.sdc.be.components.impl.instance.ComponentInstanceChangeOperationOrchestrator; import org.openecomp.sdc.be.components.impl.utils.DirectivesUtil; @@ -130,6 +129,7 @@ import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator; import org.openecomp.sdc.be.resources.data.ComponentInstanceData; import org.openecomp.sdc.be.user.Role; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; @@ -184,6 +184,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { private CompositionBusinessLogic compositionBusinessLogic; @Autowired private ContainerInstanceTypesData containerInstanceTypesData; + private final ToscaFunctionValidator toscaFunctionValidator; @Autowired public ComponentInstanceBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, @@ -193,7 +194,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL, ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator, ForwardingPathOperation forwardingPathOperation, NodeFilterOperation nodeFilterOperation, - ArtifactsOperations artifactToscaOperation) { + ArtifactsOperations artifactToscaOperation, final ToscaFunctionValidator toscaFunctionValidator) { super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation); this.componentInstanceOperation = componentInstanceOperation; @@ -202,6 +203,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { this.onChangeInstanceOperationOrchestrator = onChangeInstanceOperationOrchestrator; this.forwardingPathOperation = forwardingPathOperation; this.nodeFilterOperation = nodeFilterOperation; + this.toscaFunctionValidator = toscaFunctionValidator; } public ComponentInstance createComponentInstance(String containerComponentParam, String containerComponentId, String userId, @@ -1962,12 +1964,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { validatePropertyExistsOnComponent(property, containerComponent, foundResourceInstance); String propertyParentUniqueId = property.getParentUniqueId(); if (property.isToscaFunction()) { - if (property.getToscaFunction().getType() == null) { - throw ToscaFunctionExceptionSupplier.missingFunctionType().get(); - } - if (property.isToscaGetFunction()) { - validateToscaGetFunction(property, containerComponent); - } + toscaFunctionValidator.validate(property, containerComponent); property.setValue(property.getToscaFunction().getValue()); } Either updatedPropertyValue = updatePropertyObjectValue(property, containerComponent.getModel()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogic.java index ae9ab04a87..e24b414878 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogic.java @@ -58,6 +58,7 @@ import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; +import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType; @@ -96,6 +97,8 @@ import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.jsongraph.util.CommonUtility; +import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum; import org.openecomp.sdc.common.log.elements.LoggerSupportability; import org.openecomp.sdc.common.log.enums.LogLevel; import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions; @@ -801,23 +804,29 @@ public class GroupBusinessLogic extends BaseBusinessLogic { public Either validateAndUpdateGroupInstancePropertyValues(String componentId, String instanceId, GroupInstance oldGroupInstance, List newProperties) { - Either actionResult = null; - List validatedReducedNewProperties = validateReduceGroupInstancePropertiesBeforeUpdate(oldGroupInstance, newProperties); - Either updateGroupInstanceResult = groupsOperation + final Either ownerComponentEither = + toscaOperationFacade.getToscaElement(componentId, JsonParseFlagEnum.ParseAll); + if (ownerComponentEither.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to fetch component {}. Status is {} ", componentId); + final ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(ownerComponentEither.right().value()); + return Either.right(componentsUtils.getResponseFormat(actionStatus, componentId)); + } + + final List validatedReducedNewProperties = + validateReduceGroupInstancePropertiesBeforeUpdate(ownerComponentEither.left().value(), oldGroupInstance, newProperties); + final Either updateGroupInstanceResult = groupsOperation .updateGroupInstancePropertyValuesOnGraph(componentId, instanceId, oldGroupInstance, validatedReducedNewProperties); if (updateGroupInstanceResult.isRight()) { log.debug("Failed to update group instance {} property values. ", oldGroupInstance.getName()); - actionResult = Either + return Either .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(updateGroupInstanceResult.right().value()))); } - if (actionResult == null) { - actionResult = Either.left(updateGroupInstanceResult.left().value()); - } - return actionResult; + return Either.left(updateGroupInstanceResult.left().value()); } - private List validateReduceGroupInstancePropertiesBeforeUpdate(GroupInstance oldGroupInstance, - List newProperties) { + private List validateReduceGroupInstancePropertiesBeforeUpdate(final Component groupOwnerComponent, + final GroupInstance oldGroupInstance, + final List newProperties) { Boolean validationRes = null; List actionResult = null; Map existingProperties = oldGroupInstance.convertToGroupInstancesProperties().stream() @@ -828,7 +837,8 @@ public class GroupBusinessLogic extends BaseBusinessLogic { try { for (GroupInstanceProperty currNewProperty : newProperties) { currPropertyName = currNewProperty.getName(); - validationRes = handleAndAddProperty(reducedProperties, newPropertyValues, currNewProperty, existingProperties.get(currPropertyName)); + validationRes = handleAndAddProperty(groupOwnerComponent, reducedProperties, newPropertyValues, + currNewProperty, existingProperties.get(currPropertyName)); } if (validationRes == null || validationRes) { Map existingPropertyValues = new EnumMap<>(PropertyNames.class); @@ -858,27 +868,25 @@ public class GroupBusinessLogic extends BaseBusinessLogic { } } - private Boolean handleAndAddProperty(List reducedProperties, Map newPropertyValues, - GroupInstanceProperty currNewProperty, GroupInstanceProperty currExistingProperty) { - Boolean validationRes = null; - String currPropertyName = currNewProperty.getName(); - PropertyNames propertyName = PropertyNames.findName(currPropertyName); + private boolean handleAndAddProperty(final Component groupOwner, final List reducedProperties, + final Map newPropertyValues, final GroupInstanceProperty currNewProperty, + final GroupInstanceProperty currExistingProperty) { + final String currPropertyName = currNewProperty.getName(); + final PropertyNames propertyName = PropertyNames.findName(currPropertyName); try { if (currExistingProperty == null) { log.warn("The value of property with the name {} cannot be updated. The property not found on group instance. ", currPropertyName); } else if (isUpdatable(propertyName)) { - validationRes = validateAndUpdatePropertyValue(currNewProperty, currExistingProperty); + validateAndUpdatePropertyValue(groupOwner, currNewProperty, currExistingProperty); addPropertyUpdatedValues(reducedProperties, propertyName, newPropertyValues, currNewProperty, currExistingProperty); } else { validateImmutableProperty(currExistingProperty, currNewProperty); } - if (validationRes == null) { - validationRes = true; - } - } catch (Exception e) { - log.error("Exception occured during handle and adding property. The message is {}", e.getMessage(), e); + } catch (final Exception e) { + log.error("Exception occurred during handle and adding property. The message is {}", e.getMessage(), e); + return false; } - return validationRes; + return true; } private boolean isUpdatable(PropertyNames updatablePropertyName) { @@ -918,7 +926,8 @@ public class GroupBusinessLogic extends BaseBusinessLogic { return result; } - private Boolean validateAndUpdatePropertyValue(GroupInstanceProperty newProperty, GroupInstanceProperty existingProperty) { + private void validateAndUpdatePropertyValue(final Component groupOwner, final GroupInstanceProperty newProperty, + final GroupInstanceProperty existingProperty) { String parentValue = existingProperty.getParentValue(); newProperty.setParentValue(parentValue); if (StringUtils.isEmpty(newProperty.getValue())) { @@ -927,13 +936,12 @@ public class GroupBusinessLogic extends BaseBusinessLogic { if (StringUtils.isEmpty(existingProperty.getValue())) { existingProperty.setValue(parentValue); } - StorageOperationStatus status = groupOperation.validateAndUpdatePropertyValue(newProperty); + StorageOperationStatus status = groupOperation.validateAndUpdatePropertyValue(groupOwner, newProperty); if (status != StorageOperationStatus.OK) { log.debug("Failed to validate property value {} of property with name {}. Status is {}. ", newProperty.getValue(), newProperty.getName(), status); throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status)); } - return true; } private void validateImmutableProperty(GroupProperty oldProperty, GroupProperty newProperty) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogicNew.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogicNew.java index e810999504..25b62bb44f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogicNew.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogicNew.java @@ -86,7 +86,7 @@ public class GroupBusinessLogicNew { List newProperties) { Component component = accessValidations.validateUserCanWorkOnComponent(componentId, componentType, userId, "UPDATE GROUP PROPERTIES"); GroupDefinition currentGroup = getGroup(component, groupUniqueId); - validateUpdatedPropertiesAndSetEmptyValues(currentGroup, newProperties); + validateUpdatedPropertiesAndSetEmptyValues(component, currentGroup, newProperties); return groupsOperation.updateGroupPropertiesOnComponent(componentId, currentGroup, newProperties, PromoteVersionEnum.MINOR).left() .on(this::onUpdatePropertyError); } @@ -122,7 +122,7 @@ public class GroupBusinessLogicNew { () -> new ByActionStatusComponentException(ActionStatus.GROUP_IS_MISSING, component.getSystemName(), component.getActualComponentType())); } - private void validateUpdatedPropertiesAndSetEmptyValues(GroupDefinition originalGroup, List groupPropertiesToUpdate) { + private void validateUpdatedPropertiesAndSetEmptyValues(Component groupOwner, GroupDefinition originalGroup, List groupPropertiesToUpdate) { if (CollectionUtils.isEmpty(groupPropertiesToUpdate)) { throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, StringUtils.EMPTY); } @@ -140,13 +140,10 @@ public class GroupBusinessLogicNew { if (!isOnlyGroupPropertyValueChanged(gp, originalProperties.get(updatedPropertyName))) { throw new ByActionStatusComponentException(ActionStatus.INVALID_PROPERTY, updatedPropertyName); } - if (gp.hasToscaFunction()) { - gp.setValue(gp.getToscaFunction().getValue()); - } if (StringUtils.isEmpty(gp.getValue())) { gp.setValue(originalProperties.get(updatedPropertyName).getDefaultValue()); } - StorageOperationStatus sos = groupOperation.validateAndUpdatePropertyValue(gp); + StorageOperationStatus sos = groupOperation.validateAndUpdatePropertyValue(groupOwner, gp); if (StorageOperationStatus.OK != sos) { throw new StorageException(sos, updatedPropertyName); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PolicyBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PolicyBusinessLogic.java index 2f01ef3ecc..f536cffaba 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PolicyBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PolicyBusinessLogic.java @@ -45,6 +45,7 @@ import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator; import org.openecomp.sdc.be.components.validation.PolicyUtils; import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.datatypes.elements.GetPolicyValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType; @@ -67,6 +68,7 @@ import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; import org.openecomp.sdc.be.model.operations.api.IGroupOperation; import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; import org.openecomp.sdc.common.datastructure.Wrapper; import org.openecomp.sdc.common.log.elements.LoggerSupportability; @@ -624,7 +626,10 @@ public class PolicyBusinessLogic extends BaseBusinessLogic { filter.setIgnorePolicies(false); filter.setIgnoreUsers(false); filter.setIgnoreComponentInstances(false); + filter.setIgnoreComponentInstancesAttributes(false); + filter.setIgnoreComponentInstancesProperties(false); filter.setIgnoreGroups(false); + filter.setIgnoreInputs(false); return validateComponentExists(componentId, componentType, filter); } @@ -636,7 +641,7 @@ public class PolicyBusinessLogic extends BaseBusinessLogic { private PolicyDefinition validateAndUpdatePolicyProperties(Component component, String policyId, PropertyDataDefinition[] properties) { PolicyDefinition policyById = getPolicyById(component, policyId); - policyById = validateUpdatePolicyPropertiesBeforeUpdate(policyById, properties); + policyById = validateUpdatePolicyPropertiesBeforeUpdate(component, policyById, properties); return updatePolicyOfComponent(component.getUniqueId(), policyById); } @@ -645,16 +650,16 @@ public class PolicyBusinessLogic extends BaseBusinessLogic { .on(ce -> componentExceptionPolicyDefinition(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(ce)))); } - private PolicyDefinition validateUpdatePolicyPropertiesBeforeUpdate(PolicyDefinition policy, PropertyDataDefinition[] newProperties) { + private PolicyDefinition validateUpdatePolicyPropertiesBeforeUpdate(final Component policyOwnerComponent, PolicyDefinition policy, PropertyDataDefinition[] newProperties) { if (CollectionUtils.isEmpty(policy.getProperties())) { log.error( "#validateUpdatePolicyPropertiesBeforeUpdate - failed to update properites of the policy. Properties were not found on the policy. "); throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND); } - return updatePropertyValues(policy, newProperties); + return updatePropertyValues(policyOwnerComponent, policy, newProperties); } - private PolicyDefinition updatePropertyValues(PolicyDefinition policy, PropertyDataDefinition[] newProperties) { + private PolicyDefinition updatePropertyValues(final Component policyOwnerComponent, PolicyDefinition policy, PropertyDataDefinition[] newProperties) { Map oldProperties = policy.getProperties().stream() .collect(toMap(PropertyDataDefinition::getName, Function.identity())); for (PropertyDataDefinition newProperty : newProperties) { @@ -663,12 +668,34 @@ public class PolicyBusinessLogic extends BaseBusinessLogic { policy.getName()); throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, newProperty.getName()); } - String newPropertyValueEither = updateInputPropertyObjectValue(newProperty); - oldProperties.get(newProperty.getName()).setValue(newPropertyValueEither); + final String newPropertyValueEither = updatePropertyValue(policyOwnerComponent, newProperty); + final PropertyDataDefinition currentProperty = oldProperties.get(newProperty.getName()); + currentProperty.setValue(newPropertyValueEither); + currentProperty.setToscaFunction(newProperty.getToscaFunction()); } return policy; } + private String updatePropertyValue(final Component policyOwnerComponent, final T property) { + Either isValid = propertyOperation + .validateAndUpdatePropertyValue(policyOwnerComponent, property, + componentsUtils.getAllDataTypes(applicationDataTypeCache, property.getModel()) + ); + if (isValid.isRight()) { + Boolean res = isValid.right().value(); + if (Boolean.FALSE.equals(res)) { + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse( + DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT))); + } + } else { + Object object = isValid.left().value(); + if (object != null) { + return object.toString(); + } + } + return property.getValue(); + } + private PolicyDefinition deletePolicy(Component component, String policyId) { PolicyDefinition policyById = getPolicyById(component, policyId); return removePolicyFromComponent(component, policyById); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/validation/ToscaFunctionValidatorImpl.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/validation/ToscaFunctionValidatorImpl.java new file mode 100644 index 0000000000..ed37347a45 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/validation/ToscaFunctionValidatorImpl.java @@ -0,0 +1,206 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl.validation; + +import fj.data.Either; +import java.util.List; +import java.util.Map; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.onap.sdc.tosca.datatypes.model.PropertyType; +import org.openecomp.sdc.be.components.impl.exceptions.ToscaFunctionExceptionSupplier; +import org.openecomp.sdc.be.components.impl.exceptions.ToscaGetFunctionExceptionSupplier; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; +import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.ToscaPropertyData; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; +import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator; + +@org.springframework.stereotype.Component +public class ToscaFunctionValidatorImpl implements ToscaFunctionValidator { + + private final ApplicationDataTypeCache applicationDataTypeCache; + + public ToscaFunctionValidatorImpl(final ApplicationDataTypeCache applicationDataTypeCache) { + this.applicationDataTypeCache = applicationDataTypeCache; + } + + @Override + public void validate(T property, final Component containerComponent) { + if (property.getToscaFunction().getType() == null) { + throw ToscaFunctionExceptionSupplier.missingFunctionType().get(); + } + if (property.isToscaGetFunction()) { + validateToscaGetFunction(property, containerComponent); + } + } + + private void validateToscaGetFunction(T property, Component parentComponent) { + final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction(); + validateGetToscaFunctionAttributes(toscaGetFunction); + validateGetPropertySource(toscaGetFunction.getFunctionType(), toscaGetFunction.getPropertySource()); + if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_INPUT) { + validateGetFunction(property, parentComponent.getInputs(), parentComponent.getModel()); + return; + } + if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_PROPERTY) { + if (toscaGetFunction.getPropertySource() == PropertySource.SELF) { + validateGetFunction(property, parentComponent.getProperties(), parentComponent.getModel()); + } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) { + final ComponentInstance componentInstance = + parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId()) + .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName())); + validateGetFunction(property, componentInstance.getProperties(), parentComponent.getModel()); + } + + return; + } + if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_ATTRIBUTE) { + if (toscaGetFunction.getPropertySource() == PropertySource.SELF) { + validateGetFunction(property, parentComponent.getAttributes(), parentComponent.getModel()); + } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) { + final ComponentInstance componentInstance = + parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId()) + .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName())); + validateGetFunction(property, componentInstance.getAttributes(), parentComponent.getModel()); + } + + return; + } + + throw ToscaGetFunctionExceptionSupplier.functionNotSupported(toscaGetFunction.getFunctionType()).get(); + } + + private void validateGetFunction(final T property, + final List parentProperties, + final String model) { + final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction(); + if (CollectionUtils.isEmpty(parentProperties)) { + throw ToscaGetFunctionExceptionSupplier + .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource(), + toscaGetFunction.getFunctionType() + ).get(); + } + final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId(); + ToscaPropertyData referredProperty = parentProperties.stream() + .filter(property1 -> getFunctionPropertyUniqueId.equals(property1.getUniqueId())) + .findFirst() + .orElseThrow(ToscaGetFunctionExceptionSupplier + .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource() + , toscaGetFunction.getFunctionType()) + ); + if (toscaGetFunction.isSubProperty()) { + referredProperty = findSubProperty(referredProperty, toscaGetFunction, model); + } + + if (!property.getType().equals(referredProperty.getType())) { + throw ToscaGetFunctionExceptionSupplier + .propertyTypeDiverge(toscaGetFunction.getType(), referredProperty.getType(), property.getType()).get(); + } + if (PropertyType.typeHasSchema(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getSchemaType())) { + throw ToscaGetFunctionExceptionSupplier + .propertySchemaDiverge(toscaGetFunction.getType(), referredProperty.getSchemaType(), property.getSchemaType()).get(); + } + } + + private void validateGetToscaFunctionAttributes(final ToscaGetFunctionDataDefinition toscaGetFunction) { + if (toscaGetFunction.getFunctionType() == null) { + throw ToscaGetFunctionExceptionSupplier.targetFunctionTypeNotFound().get(); + } + if (toscaGetFunction.getPropertySource() == null) { + throw ToscaGetFunctionExceptionSupplier.targetPropertySourceNotFound(toscaGetFunction.getFunctionType()).get(); + } + if (CollectionUtils.isEmpty(toscaGetFunction.getPropertyPathFromSource())) { + throw ToscaGetFunctionExceptionSupplier + .targetSourcePathNotFound(toscaGetFunction.getFunctionType()).get(); + } + if (StringUtils.isEmpty(toscaGetFunction.getSourceName()) || StringUtils.isBlank(toscaGetFunction.getSourceName())) { + throw ToscaGetFunctionExceptionSupplier.sourceNameNotFound(toscaGetFunction.getPropertySource()).get(); + } + if (StringUtils.isEmpty(toscaGetFunction.getSourceUniqueId()) || StringUtils.isBlank(toscaGetFunction.getSourceUniqueId())) { + throw ToscaGetFunctionExceptionSupplier.sourceIdNotFound(toscaGetFunction.getPropertySource()).get(); + } + if (StringUtils.isEmpty(toscaGetFunction.getPropertyName()) || StringUtils.isBlank(toscaGetFunction.getPropertyName())) { + throw ToscaGetFunctionExceptionSupplier.propertyNameNotFound(toscaGetFunction.getPropertySource()).get(); + } + if (StringUtils.isEmpty(toscaGetFunction.getPropertyUniqueId()) || StringUtils.isBlank(toscaGetFunction.getPropertyUniqueId())) { + throw ToscaGetFunctionExceptionSupplier.propertyIdNotFound(toscaGetFunction.getPropertySource()).get(); + } + } + + private void validateGetPropertySource(final ToscaGetFunctionType functionType, final PropertySource propertySource) { + if (functionType == ToscaGetFunctionType.GET_INPUT && propertySource != PropertySource.SELF) { + throw ToscaGetFunctionExceptionSupplier + .targetSourceNotSupported(functionType, propertySource).get(); + } + if (functionType == ToscaGetFunctionType.GET_PROPERTY && !List.of(PropertySource.SELF, PropertySource.INSTANCE).contains(propertySource)) { + throw ToscaGetFunctionExceptionSupplier + .targetSourceNotSupported(functionType, propertySource).get(); + } + } + + private ToscaPropertyData findSubProperty(final ToscaPropertyData referredProperty, + final ToscaGetFunctionDataDefinition toscaGetFunction, + final String model) { + final Map dataTypeMap = loadDataTypes(model); + final List propertyPathFromSource = toscaGetFunction.getPropertyPathFromSource(); + DataTypeDefinition dataType = dataTypeMap.get(referredProperty.getType()); + if (dataType == null) { + throw ToscaGetFunctionExceptionSupplier + .propertyDataTypeNotFound(propertyPathFromSource.get(0), referredProperty.getType(), toscaGetFunction.getFunctionType()).get(); + } + ToscaPropertyData foundProperty = referredProperty; + for (int i = 1; i < propertyPathFromSource.size(); i++) { + final String currentPropertyName = propertyPathFromSource.get(i); + foundProperty = dataType.getProperties().stream() + .filter(propertyDefinition -> currentPropertyName.equals(propertyDefinition.getName())).findFirst() + .orElseThrow( + ToscaGetFunctionExceptionSupplier + .propertyNotFoundOnTarget(propertyPathFromSource.subList(0, i), toscaGetFunction.getPropertySource(), + toscaGetFunction.getFunctionType()) + ); + dataType = dataTypeMap.get(foundProperty.getType()); + if (dataType == null) { + throw ToscaGetFunctionExceptionSupplier + .propertyDataTypeNotFound(propertyPathFromSource.subList(0, i), foundProperty.getType(), + toscaGetFunction.getFunctionType()).get(); + } + } + return foundProperty; + } + + private Map loadDataTypes(String model) { + final Either, JanusGraphOperationStatus> dataTypeEither = + applicationDataTypeCache.getAll(model); + if (dataTypeEither.isRight()) { + throw ToscaGetFunctionExceptionSupplier.couldNotLoadDataTypes(model).get(); + } + return dataTypeEither.left().value(); + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java b/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java index 0c78b1fdef..b38210116c 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java @@ -66,6 +66,7 @@ import org.springframework.core.annotation.Order; "org.openecomp.sdc.be.filters", "org.openecomp.sdc.be.plugins", "org.openecomp.sdc.be.togglz", + "org.openecomp.sdc.be.model.cache", "org.openecomp.sdc.be.ui.mapper"}) // @formatter:on public class CatalogBESpringConfig { diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java index 96c6762d74..3a5f40cb8c 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java @@ -49,13 +49,9 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Optional; import java.util.Set; -import java.util.stream.Stream; import mockit.Deencapsulation; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.assertj.core.util.Lists; @@ -64,17 +60,12 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; -import org.openecomp.sdc.be.components.impl.exceptions.ToscaFunctionExceptionSupplier; -import org.openecomp.sdc.be.components.impl.exceptions.ToscaGetFunctionExceptionSupplier; import org.openecomp.sdc.be.components.validation.UserValidations; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; @@ -129,6 +120,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationE import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.GraphLockOperation; import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; +import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import org.openecomp.sdc.common.api.ArtifactTypeEnum; import org.openecomp.sdc.common.api.ConfigurationSource; @@ -196,6 +188,8 @@ class ComponentInstanceBusinessLogicTest { private ContainerInstanceTypesData containerInstanceTypeData; @Mock private CompositionBusinessLogic compositionBusinessLogic; + @Mock + private ToscaFunctionValidator toscaFunctionValidator; private Component service; private Component resource; @@ -222,7 +216,7 @@ class ComponentInstanceBusinessLogicTest { void init() { MockitoAnnotations.openMocks(this); componentInstanceBusinessLogic = new ComponentInstanceBusinessLogic(null, null, null, null, null, null, null, artifactsBusinessLogic, null, - null, forwardingPathOperation, null, null); + null, forwardingPathOperation, null, null, toscaFunctionValidator); componentInstanceBusinessLogic.setComponentsUtils(componentsUtils); componentInstanceBusinessLogic.setToscaOperationFacade(toscaOperationFacade); componentInstanceBusinessLogic.setUserValidations(userValidations); @@ -369,408 +363,7 @@ class ComponentInstanceBusinessLogicTest { assertThat(responseFormatEither.left().value()).isEqualTo(properties); } - @Test - void testToscaGetFunctionValidation() { - final String userId = "userId"; - final String containerComponentId = "containerComponentId"; - final String containerComponentName = "containerComponentName"; - final String resourceInstanceId = "resourceInstanceId"; - final String inputName = "myInputToGet"; - final String inputId = String.format("%s.%s", containerComponentId, inputName); - final String schemaType = "string"; - //creating instance list of string property with get_input value - final ComponentInstanceProperty propertyGetInput = new ComponentInstanceProperty(); - propertyGetInput.setName("getInputProperty"); - propertyGetInput.setPropertyId(String.format("%s.%s", containerComponentId, "getInputProperty")); - propertyGetInput.setValue(String.format("get_input: [\"%s\"]", inputName)); - propertyGetInput.setType("list"); - final SchemaDefinition listStringPropertySchema = createSchema(schemaType); - propertyGetInput.setSchema(listStringPropertySchema); - propertyGetInput.setToscaFunction( - createGetToscaFunction(inputName, inputId, List.of(propertyGetInput.getName()), PropertySource.SELF, ToscaGetFunctionType.GET_INPUT, - containerComponentId, containerComponentName) - ); - //creating instance map of string property with get_input value to a second level property: - // get_input: ["property1", "subProperty1", "subProperty2"] - final String getPropertyPropertyName = "getPropertyProperty"; - final List containerPropertyPath = List.of("property1", "subProperty1", "subProperty2"); - final String containerPropertyId = String.format("%s.%s", containerComponentId, containerPropertyPath.get(0)); - final String mapToscaType = "map"; - final ComponentInstanceProperty propertyGetProperty = createComponentInstanceProperty( - String.format("%s.%s", containerComponentId, getPropertyPropertyName), - getPropertyPropertyName, - mapToscaType, - "string", - String.format("\"get_property\": [\"%s\", \"%s\"]", PropertySource.SELF, String.join("\", \"", containerPropertyPath)), - createGetToscaFunction(containerPropertyPath.get(containerPropertyPath.size() - 1), containerPropertyId, - containerPropertyPath, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, containerComponentId, containerComponentName) - ); - - //creating component that has the instance properties - final Component component = new Service(); - component.setUniqueId(containerComponentId); - component.setName(containerComponentName); - component.setLastUpdaterUserId(userId); - component.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); - //adding instance properties to the component - final List resourceInstanceProperties = List.of(propertyGetInput, propertyGetProperty); - final Map> componentInstanceProps = new HashMap<>(); - componentInstanceProps.put(resourceInstanceId, resourceInstanceProperties); - component.setComponentInstancesProperties(componentInstanceProps); - - //creating component input that will be gotten by the get_input instance property - final var inputDefinition = new InputDefinition(); - inputDefinition.setName(inputName); - inputDefinition.setUniqueId(inputId); - inputDefinition.setType(propertyGetInput.getType()); - inputDefinition.setSchema(listStringPropertySchema); - component.setInputs(List.of(inputDefinition)); - - //creating component property that contains the sub property that will be gotten by the get_property instance property - final var propertyDefinition = new PropertyDefinition(); - propertyDefinition.setName(containerPropertyPath.get(0)); - propertyDefinition.setUniqueId(containerPropertyId); - final String property1Type = "property1.datatype"; - propertyDefinition.setType(property1Type); - component.setProperties(List.of(propertyDefinition)); - //creating resource instance to be added to the component - final ComponentInstance resourceInstance = createComponentInstance("resourceInstance"); - resourceInstance.setUniqueId(resourceInstanceId); - component.setComponentInstances(List.of(resourceInstance)); - - mockComponentForToscaGetFunctionValidation(component); - - //creating data types for "map", and sub properties - final Map allDataTypesMap = new HashMap<>(); - allDataTypesMap.put(mapToscaType, new DataTypeDefinition()); - - final String subProperty1Type = "subProperty1.datatype"; - allDataTypesMap.put(property1Type, createDataType(property1Type, Map.of(containerPropertyPath.get(1), subProperty1Type))); - - final var subProperty2Property = new PropertyDefinition(); - subProperty2Property.setName(containerPropertyPath.get(2)); - subProperty2Property.setType(propertyGetProperty.getType()); - subProperty2Property.setSchema(propertyGetProperty.getSchema()); - allDataTypesMap.put(subProperty1Type, createDataType(subProperty1Type, List.of(subProperty2Property))); - - when(applicationDataTypeCache.getAll(component.getModel())).thenReturn(Either.left(allDataTypesMap)); - //when - final Either, ResponseFormat> actualResponseFormat = componentInstanceBusinessLogic - .createOrUpdatePropertiesValues( - ComponentTypeEnum.RESOURCE_INSTANCE, containerComponentId, resourceInstanceId, resourceInstanceProperties, userId); - //then - assertTrue(actualResponseFormat.isLeft()); - assertThat(actualResponseFormat.left().value()).isEqualTo(resourceInstanceProperties); - } - - @Test - void testToscaGetPropertyOnInstanceValidation() { - final String userId = "userId"; - final String containerComponentId = "containerComponentId"; - final String containerComponentName = "containerComponentName"; - final String instanceUniqueId = String.format("%s.%s", containerComponentId, "instanceId"); - - final List parentPropertyPath = List.of("property1"); - final String containerPropertyId = String.format("%s.%s", containerComponentId, parentPropertyPath.get(0)); - final ComponentInstanceProperty getPropertyOnInstanceProperty = createComponentInstanceProperty( - String.format("%s.%s", containerComponentId, "getPropertyOnInstanceProperty"), - "getPropertyOnInstanceProperty", - "string", - null, - String.format("\"get_property\": [\"%s\", \"%s\"]", PropertySource.INSTANCE, parentPropertyPath.get(0)), - createGetToscaFunction(parentPropertyPath.get(0), containerPropertyId, parentPropertyPath, PropertySource.INSTANCE, - ToscaGetFunctionType.GET_PROPERTY, instanceUniqueId, containerComponentName) - ); - - //creating component that has the instance properties - final Component component = new Service(); - component.setUniqueId(containerComponentId); - component.setName(containerComponentName); - component.setLastUpdaterUserId(userId); - component.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); - //adding instance properties to the component - final List resourceInstanceProperties = List.of(getPropertyOnInstanceProperty); - final Map> componentInstanceProps = new HashMap<>(); - componentInstanceProps.put(instanceUniqueId, resourceInstanceProperties); - component.setComponentInstancesProperties(componentInstanceProps); - - //creating resource property that will be get - final var propertyDefinition = new PropertyDefinition(); - propertyDefinition.setName(parentPropertyPath.get(0)); - propertyDefinition.setUniqueId(containerPropertyId); - final String property1Type = "string"; - propertyDefinition.setType(property1Type); - //creating resource instance to be added to the component - final ComponentInstance resourceInstance = createComponentInstance("resourceInstance"); - resourceInstance.setUniqueId(instanceUniqueId); - resourceInstance.setProperties(List.of(propertyDefinition)); - component.setComponentInstances(List.of(resourceInstance)); - - mockComponentForToscaGetFunctionValidation(component); - - //when - final Either, ResponseFormat> actualResponseFormat = componentInstanceBusinessLogic - .createOrUpdatePropertiesValues( - ComponentTypeEnum.RESOURCE_INSTANCE, containerComponentId, instanceUniqueId, resourceInstanceProperties, userId); - //then - assertTrue(actualResponseFormat.isLeft()); - assertThat(actualResponseFormat.left().value()).isEqualTo(resourceInstanceProperties); - } - - private DataTypeDefinition createDataType(final String name, final Map propertyNameAndTypeMap) { - final var dataTypeDefinition = new DataTypeDefinition(); - dataTypeDefinition.setName(name); - if (MapUtils.isNotEmpty(propertyNameAndTypeMap)) { - for (final Entry propertyEntry : propertyNameAndTypeMap.entrySet()) { - final var propertyDefinition = new PropertyDefinition(); - propertyDefinition.setName(propertyEntry.getKey()); - propertyDefinition.setType(propertyEntry.getValue()); - dataTypeDefinition.setProperties(List.of(propertyDefinition)); - } - } - return dataTypeDefinition; - } - - private DataTypeDefinition createDataType(final String name, final List propertyList) { - final var dataTypeDefinition = new DataTypeDefinition(); - dataTypeDefinition.setName(name); - if (CollectionUtils.isNotEmpty(propertyList)) { - dataTypeDefinition.setProperties(propertyList); - } - return dataTypeDefinition; - } - - private ComponentInstanceProperty createComponentInstanceProperty(final String uniqueId, final String name, final String type, - final String schemaType, final String value, - final ToscaGetFunctionDataDefinition toscaGetFunction) { - final var componentInstanceProperty = new ComponentInstanceProperty(); - componentInstanceProperty.setName(name); - componentInstanceProperty.setUniqueId(uniqueId); - componentInstanceProperty.setType(type); - componentInstanceProperty.setValue(value); - if (schemaType != null) { - final SchemaDefinition schemaDefinition = createSchema(schemaType); - componentInstanceProperty.setSchema(schemaDefinition); - } - if (toscaGetFunction != null) { - componentInstanceProperty.setToscaFunction(toscaGetFunction); - } - - return componentInstanceProperty; - } - - @Test - void testToscaGetFunctionValidation_schemaDivergeTest() { - final String userId = "userId"; - final String containerComponentId = "containerComponentId"; - final String containerComponentName = "containerComponentName"; - final String resourceInstanceId = "resourceInstanceId"; - final String inputName = "myInputToGet"; - final String inputId = String.format("%s.%s", containerComponentId, inputName); - final String propertyName = "getInputProperty"; - final String propertyId = String.format("%s.%s", containerComponentId, propertyName); - final String propertyType = "list"; - final List properties = new ArrayList<>(); - final ComponentInstanceProperty propertyGetInput = createComponentInstanceProperty( - propertyId, - "getInputProperty", - propertyType, - "string", - String.format("get_input: [\"%s\"]", inputName), - createGetToscaFunction(inputName, inputId, List.of(propertyName), PropertySource.SELF, ToscaGetFunctionType.GET_INPUT, - containerComponentId, containerComponentName) - ); - properties.add(propertyGetInput); - - final Component component = new Service(); - component.setUniqueId(containerComponentId); - component.setName(containerComponentName); - component.setLastUpdaterUserId(userId); - component.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); - - var inputDefinition = new InputDefinition(); - inputDefinition.setName(inputName); - inputDefinition.setUniqueId(inputId); - inputDefinition.setType(propertyType); - inputDefinition.setSchema(createSchema("integer")); - component.setInputs(List.of(inputDefinition)); - - final Map> componentInstanceProps = new HashMap<>(); - componentInstanceProps.put(resourceInstanceId, properties); - component.setComponentInstancesProperties(componentInstanceProps); - - final ComponentInstance resourceInstance = createComponentInstance("componentInstance1"); - resourceInstance.setUniqueId(resourceInstanceId); - component.setComponentInstances(List.of(resourceInstance)); - - mockComponentForToscaGetFunctionValidation(component); - //when - final Either, ResponseFormat> responseFormatEither = - componentInstanceBusinessLogic - .createOrUpdatePropertiesValues(ComponentTypeEnum.RESOURCE_INSTANCE, containerComponentId, resourceInstanceId, properties, userId); - //then - assertTrue(responseFormatEither.isRight(), "Expecting an error"); - final ResponseFormat actualResponse = responseFormatEither.right().value(); - final ResponseFormat expectedResponse = - ToscaGetFunctionExceptionSupplier - .propertySchemaDiverge(propertyGetInput.getToscaFunction().getType(), inputDefinition.getSchemaType(), - propertyGetInput.getSchemaType()) - .get().getResponseFormat(); - assertEquals(expectedResponse.getFormattedMessage(), actualResponse.getFormattedMessage()); - assertEquals(expectedResponse.getStatus(), actualResponse.getStatus()); - } - - @Test - void testToscaGetFunctionValidation_propertyTypeDivergeTest() { - final String userId = "userId"; - final String containerComponentId = "containerComponentId"; - final String containerComponentName = "containerComponentName"; - final String resourceInstanceId = "resourceInstanceId"; - final String inputName = "myInputToGet"; - final String inputId = String.format("%s.%s", containerComponentId, inputName); - final String propertyName = "getInputProperty"; - final String propertyId = String.format("%s.%s", containerComponentId, propertyName); - final String propertyType = "string"; - final List properties = new ArrayList<>(); - final ComponentInstanceProperty propertyGetInput = createComponentInstanceProperty( - propertyId, - "getInputProperty", - propertyType, - "string", - String.format("get_input: [\"%s\"]", inputName), - createGetToscaFunction(inputName, inputId, List.of(propertyName), PropertySource.SELF, ToscaGetFunctionType.GET_INPUT, - containerComponentId, containerComponentName) - ); - properties.add(propertyGetInput); - - final Component component = new Service(); - component.setName(containerComponentName); - component.setUniqueId(containerComponentId); - component.setLastUpdaterUserId(userId); - component.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); - - var inputDefinition = new InputDefinition(); - inputDefinition.setName(inputName); - inputDefinition.setUniqueId(inputId); - inputDefinition.setType("integer"); - component.setInputs(List.of(inputDefinition)); - - final Map> componentInstanceProps = new HashMap<>(); - componentInstanceProps.put(resourceInstanceId, properties); - component.setComponentInstancesProperties(componentInstanceProps); - - final ComponentInstance resourceInstance = createComponentInstance("componentInstance1"); - resourceInstance.setUniqueId(resourceInstanceId); - component.setComponentInstances(List.of(resourceInstance)); - - mockComponentForToscaGetFunctionValidation(component); - //when - final Either, ResponseFormat> responseFormatEither = - componentInstanceBusinessLogic - .createOrUpdatePropertiesValues(ComponentTypeEnum.RESOURCE_INSTANCE, containerComponentId, resourceInstanceId, properties, userId); - //then - assertTrue(responseFormatEither.isRight(), "Expecting an error"); - final ResponseFormat actualResponse = responseFormatEither.right().value(); - final ResponseFormat expectedResponse = - ToscaGetFunctionExceptionSupplier - .propertyTypeDiverge(propertyGetInput.getToscaFunction().getType(), inputDefinition.getType(), propertyGetInput.getType()) - .get().getResponseFormat(); - assertEquals(expectedResponse.getFormattedMessage(), actualResponse.getFormattedMessage()); - assertEquals(expectedResponse.getStatus(), actualResponse.getStatus()); - } - - @ParameterizedTest - @MethodSource("getToscaFunctionForValidation") - void testToscaGetFunctionValidation_AttributesNotFoundTest(final ToscaGetFunctionDataDefinition toscaGetFunction, - final ResponseFormat expectedValidationResponse) { - final String userId = "userId"; - final String containerComponentId = "containerComponentId"; - final String containerComponentName = "containerComponentName"; - final String resourceInstanceId = "resourceInstanceId"; - final List properties = new ArrayList<>(); - final ComponentInstanceProperty propertyGetInput = new ComponentInstanceProperty(); - propertyGetInput.setName("anyName"); - propertyGetInput.setToscaFunction(toscaGetFunction); - properties.add(propertyGetInput); - - final Component component = new Service(); - component.setName(containerComponentName); - component.setUniqueId(containerComponentId); - component.setLastUpdaterUserId(userId); - component.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); - - final Map> componentInstanceProps = new HashMap<>(); - componentInstanceProps.put(resourceInstanceId, properties); - component.setComponentInstancesProperties(componentInstanceProps); - - final ComponentInstance resourceInstance = createComponentInstance("componentInstance1"); - resourceInstance.setUniqueId(resourceInstanceId); - component.setComponentInstances(List.of(resourceInstance)); - - mockComponentForToscaGetFunctionValidation(component); - //when - final Either, ResponseFormat> responseFormatEither = - componentInstanceBusinessLogic - .createOrUpdatePropertiesValues(ComponentTypeEnum.RESOURCE_INSTANCE, containerComponentId, resourceInstanceId, properties, userId); - //then - assertTrue(responseFormatEither.isRight(), "Expecting an error"); - final ResponseFormat actualResponse = responseFormatEither.right().value(); - assertEquals(expectedValidationResponse.getFormattedMessage(), actualResponse.getFormattedMessage()); - assertEquals(expectedValidationResponse.getStatus(), actualResponse.getStatus()); - } - - @Test - void testToscaGetFunctionValidation_propertyNotFoundTest() { - final String userId = "userId"; - final String containerComponentId = "containerComponentId"; - final String containerComponentName = "containerComponentName"; - final String resourceInstanceId = "resourceInstanceId"; - final String inputName = "myInputToGet"; - final String inputId = String.format("%s.%s", containerComponentId, inputName); - final String propertyName = "getInputProperty"; - final String propertyId = String.format("%s.%s", containerComponentId, propertyName); - final String propertyType = "string"; - final List properties = new ArrayList<>(); - final ComponentInstanceProperty propertyGetInput = createComponentInstanceProperty( - propertyId, - "getInputProperty", - propertyType, - "string", - String.format("get_input: [\"%s\"]", inputName), - createGetToscaFunction(inputName, inputId, List.of(propertyName), PropertySource.SELF, ToscaGetFunctionType.GET_INPUT, - containerComponentId, containerComponentName) - ); - properties.add(propertyGetInput); - - final Component component = new Service(); - component.setName(containerComponentName); - component.setUniqueId(containerComponentId); - component.setLastUpdaterUserId(userId); - component.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); - - final Map> componentInstanceProps = new HashMap<>(); - componentInstanceProps.put(resourceInstanceId, properties); - component.setComponentInstancesProperties(componentInstanceProps); - - final ComponentInstance resourceInstance = createComponentInstance("componentInstance1"); - resourceInstance.setUniqueId(resourceInstanceId); - component.setComponentInstances(List.of(resourceInstance)); - mockComponentForToscaGetFunctionValidation(component); - //when - final Either, ResponseFormat> responseFormatEither = - componentInstanceBusinessLogic - .createOrUpdatePropertiesValues(ComponentTypeEnum.RESOURCE_INSTANCE, containerComponentId, resourceInstanceId, properties, userId); - //then - assertTrue(responseFormatEither.isRight(), "Expecting an error"); - final ResponseFormat actualResponse = responseFormatEither.right().value(); - final ResponseFormat expectedResponse = - ToscaGetFunctionExceptionSupplier - .propertyNotFoundOnTarget(inputName, PropertySource.SELF, ToscaGetFunctionType.GET_INPUT) - .get().getResponseFormat(); - assertEquals(expectedResponse.getFormattedMessage(), actualResponse.getFormattedMessage()); - assertEquals(expectedResponse.getStatus(), actualResponse.getStatus()); - } @Test void testCreateOrUpdatePropertiesValuesPropertyNotExists() { @@ -2622,102 +2215,5 @@ class ComponentInstanceBusinessLogicTest { return component; } - private void mockComponentForToscaGetFunctionValidation(final Component component) { - when(toscaOperationFacade.getToscaElement(component.getUniqueId(), JsonParseFlagEnum.ParseAll)) - .thenReturn(Either.left(component)); - when(graphLockOperation.lockComponent(component.getUniqueId(), NodeTypeEnum.ResourceInstance)) - .thenReturn(StorageOperationStatus.OK); - when(toscaOperationFacade.updateComponentInstanceMetadataOfTopologyTemplate(component)) - .thenReturn(Either.left(component)); - when(janusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK); - when(graphLockOperation.unlockComponent(component.getUniqueId(), NodeTypeEnum.ResourceInstance)) - .thenReturn(StorageOperationStatus.OK); - } - - private ToscaGetFunctionDataDefinition createGetToscaFunction(final String propertyName, final String propertyUniqueId, - final List propertyPathFromSource, - final PropertySource propertySource, final ToscaGetFunctionType functionType, - final String sourceUniqueId, - final String sourceName) { - final var toscaGetFunction = new ToscaGetFunctionDataDefinition(); - toscaGetFunction.setFunctionType(functionType); - toscaGetFunction.setPropertyUniqueId(propertyUniqueId); - toscaGetFunction.setPropertyName(propertyName); - toscaGetFunction.setPropertyPathFromSource(propertyPathFromSource); - toscaGetFunction.setPropertySource(propertySource); - toscaGetFunction.setSourceName(sourceName); - toscaGetFunction.setSourceUniqueId(sourceUniqueId); - return toscaGetFunction; - } - - private SchemaDefinition createSchema(final String schemaType) { - final var schemaDefinition = new SchemaDefinition(); - final var schemaProperty = new PropertyDefinition(); - schemaProperty.setType(schemaType); - schemaDefinition.setProperty(schemaProperty); - return schemaDefinition; - } - - private static Stream getToscaFunctionForValidation() { - final var toscaGetFunction1 = new ToscaGetFunctionDataDefinition(); - final ResponseFormat expectedResponse1 = ToscaFunctionExceptionSupplier - .missingFunctionType().get().getResponseFormat(); - - final var toscaGetFunction2 = new ToscaGetFunctionDataDefinition(); - toscaGetFunction2.setFunctionType(ToscaGetFunctionType.GET_INPUT); - final ResponseFormat expectedResponse2 = ToscaGetFunctionExceptionSupplier - .targetPropertySourceNotFound(toscaGetFunction2.getFunctionType()).get().getResponseFormat(); - - final var toscaGetFunction3 = new ToscaGetFunctionDataDefinition(); - toscaGetFunction3.setFunctionType(ToscaGetFunctionType.GET_INPUT); - toscaGetFunction3.setPropertySource(PropertySource.SELF); - final ResponseFormat expectedResponse3 = ToscaGetFunctionExceptionSupplier - .targetSourcePathNotFound(toscaGetFunction3.getFunctionType()).get().getResponseFormat(); - - final var toscaGetFunction4 = new ToscaGetFunctionDataDefinition(); - toscaGetFunction4.setFunctionType(ToscaGetFunctionType.GET_INPUT); - toscaGetFunction4.setPropertySource(PropertySource.SELF); - toscaGetFunction4.setPropertyPathFromSource(List.of("sourcePath")); - final ResponseFormat expectedResponse4 = ToscaGetFunctionExceptionSupplier - .sourceNameNotFound(toscaGetFunction4.getPropertySource()).get().getResponseFormat(); - - final var toscaGetFunction5 = new ToscaGetFunctionDataDefinition(); - toscaGetFunction5.setFunctionType(ToscaGetFunctionType.GET_INPUT); - toscaGetFunction5.setPropertySource(PropertySource.SELF); - toscaGetFunction5.setPropertyPathFromSource(List.of("sourcePath")); - toscaGetFunction5.setSourceName("sourceName"); - final ResponseFormat expectedResponse5 = ToscaGetFunctionExceptionSupplier - .sourceIdNotFound(toscaGetFunction5.getPropertySource()).get().getResponseFormat(); - - final var toscaGetFunction6 = new ToscaGetFunctionDataDefinition(); - toscaGetFunction6.setFunctionType(ToscaGetFunctionType.GET_PROPERTY); - toscaGetFunction6.setPropertySource(PropertySource.SELF); - toscaGetFunction6.setPropertyPathFromSource(List.of("sourcePath")); - toscaGetFunction6.setSourceName("sourceName"); - toscaGetFunction6.setSourceUniqueId("sourceUniqueId"); - final ResponseFormat expectedResponse6 = ToscaGetFunctionExceptionSupplier - .propertyNameNotFound(toscaGetFunction6.getPropertySource()).get().getResponseFormat(); - - final var toscaGetFunction7 = new ToscaGetFunctionDataDefinition(); - toscaGetFunction7.setFunctionType(ToscaGetFunctionType.GET_PROPERTY); - toscaGetFunction7.setPropertySource(PropertySource.SELF); - toscaGetFunction7.setPropertyPathFromSource(List.of("sourcePath")); - toscaGetFunction7.setSourceName("sourceName"); - toscaGetFunction7.setSourceUniqueId("sourceUniqueId"); - toscaGetFunction7.setPropertyName("propertyName"); - final ResponseFormat expectedResponse7 = ToscaGetFunctionExceptionSupplier - .propertyIdNotFound(toscaGetFunction7.getPropertySource()).get().getResponseFormat(); - - return Stream.of( - Arguments.of(toscaGetFunction1, expectedResponse1), - Arguments.of(toscaGetFunction2, expectedResponse2), - Arguments.of(toscaGetFunction3, expectedResponse3), - Arguments.of(toscaGetFunction4, expectedResponse4), - Arguments.of(toscaGetFunction5, expectedResponse5), - Arguments.of(toscaGetFunction6, expectedResponse6), - Arguments.of(toscaGetFunction7, expectedResponse7) - ); - } - } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogicTest.java index ac994f0797..141aae7a5a 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/GroupBusinessLogicTest.java @@ -31,6 +31,7 @@ package org.openecomp.sdc.be.components.impl; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; @@ -60,8 +61,9 @@ import org.openecomp.sdc.be.components.validation.AccessValidations; import org.openecomp.sdc.be.config.Configuration; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; -import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; +import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; @@ -174,7 +176,6 @@ class GroupBusinessLogicTest { @Test void testValidAndUpdateGrpInstancePropValues_fail() { - Either result; String componentId = "id"; String instanceId = "id"; GroupInstance oldGroupInstance = new GroupInstance(); @@ -182,11 +183,10 @@ class GroupBusinessLogicTest { List properties = new LinkedList<>(); properties.add(new PropertyDataDefinition()); oldGroupInstance.setProperties(properties); - try { - result = test.validateAndUpdateGroupInstancePropertyValues(componentId, instanceId, oldGroupInstance, newProperties); - } catch (ComponentException e) { - assertThat(e.getActionStatus()).isEqualTo(ActionStatus.GENERAL_ERROR); - } + when(toscaOperationFacade.getToscaElement(componentId, JsonParseFlagEnum.ParseAll)).thenReturn(Either.left(new Resource())); + final ComponentException actualException = assertThrows(ComponentException.class, + () -> test.validateAndUpdateGroupInstancePropertyValues(componentId, instanceId, oldGroupInstance, newProperties)); + assertEquals(ActionStatus.GENERAL_ERROR, actualException.getActionStatus()); } @Test diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/PolicyBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/PolicyBusinessLogicTest.java index 15b7706598..f54a70d3d7 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/PolicyBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/PolicyBusinessLogicTest.java @@ -23,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -250,8 +249,8 @@ class PolicyBusinessLogicTest { when(toscaOperationFacade.getToscaFullElement(COMPONENT_ID)).thenReturn(Either.left(newResource)); when(toscaOperationFacade.updatePolicyOfComponent(eq(COMPONENT_ID), any(PolicyDefinition.class), any(PromoteVersionEnum.class))).thenReturn( Either.left(policy)); - when(propertyOperation.validateAndUpdatePropertyValue(eq(null), eq(prop1), anyBoolean(), eq(null), anyMap())).thenReturn(Either.left(prop1)); - when(propertyOperation.validateAndUpdatePropertyValue(eq(null), eq(prop2), anyBoolean(), eq(null), anyMap())).thenReturn(Either.left(prop2)); + when(propertyOperation.validateAndUpdatePropertyValue(eq(newResource), eq(properties[0]), anyMap())).thenReturn(Either.left(prop1)); + when(propertyOperation.validateAndUpdatePropertyValue(eq(newResource), eq(properties[1]), anyMap())).thenReturn(Either.left(prop2)); Map createdPolicy = businessLogic.createPolicies(newResource, policies); @@ -292,8 +291,8 @@ class PolicyBusinessLogicTest { when(toscaOperationFacade.getToscaFullElement(COMPONENT_ID)).thenReturn(Either.left(newService)); when(toscaOperationFacade.updatePolicyOfComponent(eq(COMPONENT_ID), any(PolicyDefinition.class), any(PromoteVersionEnum.class))).thenReturn( Either.left(policy)); - when(propertyOperation.validateAndUpdatePropertyValue(eq(null), eq(prop1), anyBoolean(), eq(null), anyMap())).thenReturn(Either.left(prop1)); - when(propertyOperation.validateAndUpdatePropertyValue(eq(null), eq(prop2), anyBoolean(), eq(null), anyMap())).thenReturn(Either.left(prop2)); + when(propertyOperation.validateAndUpdatePropertyValue(eq(newService), eq(properties[0]), anyMap())).thenReturn(Either.left(prop1)); + when(propertyOperation.validateAndUpdatePropertyValue(eq(newService), eq(properties[1]), anyMap())).thenReturn(Either.left(prop2)); Map createdPolicy = businessLogic.createPolicies(newService, policies); @@ -408,16 +407,16 @@ class PolicyBusinessLogicTest { stubValidateAndLockSuccess(); String prop1 = "Name"; String prop2 = "Type"; - when(propertyOperation.validateAndUpdatePropertyValue(eq(null), eq(prop1), anyBoolean(), eq(null), anyMap())).thenReturn(Either.left(prop1)); - when(propertyOperation.validateAndUpdatePropertyValue(eq(null), eq(prop2), anyBoolean(), eq(null), anyMap())).thenReturn(Either.left(prop2)); + when(toscaOperationFacade.updatePolicyOfComponent(eq(COMPONENT_ID), any(PolicyDefinition.class), any(PromoteVersionEnum.class))).thenReturn( policySuccessEither); stubUnlockAndCommit(); PropertyDataDefinition[] properties = getProperties(prop1, prop2); + when(propertyOperation.validateAndUpdatePropertyValue(any(Resource.class), eq(properties[0]), anyMap())).thenReturn(Either.left(prop1)); + when(propertyOperation.validateAndUpdatePropertyValue(any(Resource.class), eq(properties[1]), anyMap())).thenReturn(Either.left(prop2)); policy.setProperties(Arrays.asList(properties)); - List response = businessLogic.updatePolicyProperties(ComponentTypeEnum.RESOURCE, COMPONENT_ID, POLICY_ID, properties, - USER_ID, true); - List updatedProperties = response; + List updatedProperties = + businessLogic.updatePolicyProperties(ComponentTypeEnum.RESOURCE, COMPONENT_ID, POLICY_ID, properties, USER_ID, true); assertEquals(2, updatedProperties.size()); } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceInstanceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceInstanceBusinessLogicTest.java index b5037179cf..8bd39af919 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceInstanceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceInstanceBusinessLogicTest.java @@ -22,10 +22,24 @@ package org.openecomp.sdc.be.components.impl; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import fj.data.Either; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.MockitoAnnotations; import org.openecomp.sdc.be.components.impl.instance.ComponentInstanceChangeOperationOrchestrator; import org.openecomp.sdc.be.components.merge.instance.ComponentInstanceMergeDataBusinessLogic; @@ -48,6 +62,7 @@ import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.ComponentInstanceOperation; import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; +import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo; import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo; @@ -55,19 +70,7 @@ import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import org.openecomp.sdc.exception.ResponseFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -public class ResourceInstanceBusinessLogicTest extends BaseBusinessLogicMock { +class ResourceInstanceBusinessLogicTest extends BaseBusinessLogicMock { private static final String RESOURCE_ID_WITH_HEAT_PARAMS = "MyResourceId"; private static final String RESOURCE_ID_NO_PAYLOAD = "NoHeatPayload"; @@ -79,77 +82,93 @@ public class ResourceInstanceBusinessLogicTest extends BaseBusinessLogicMock { private static final String USER_ID = "jh0003"; private static final long ARTIFACT_CREATION_TIME = System.currentTimeMillis(); - private final ComponentInstanceOperation componentInstanceOperation = Mockito.mock(ComponentInstanceOperation.class); - private final ArtifactsBusinessLogic artifactBusinessLogic = Mockito.mock(ArtifactsBusinessLogic.class); - private final ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL = Mockito.mock(ComponentInstanceMergeDataBusinessLogic.class); - private final ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator = Mockito.mock(ComponentInstanceChangeOperationOrchestrator.class); - private final ForwardingPathOperation forwardingPathOperation = Mockito.mock(ForwardingPathOperation.class); - private final NodeFilterOperation serviceFilterOperation = Mockito.mock(NodeFilterOperation.class); + private final ComponentInstanceOperation componentInstanceOperation = mock(ComponentInstanceOperation.class); + private final ArtifactsBusinessLogic artifactBusinessLogic = mock(ArtifactsBusinessLogic.class); + private final ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL = mock(ComponentInstanceMergeDataBusinessLogic.class); + private final ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator = + mock(ComponentInstanceChangeOperationOrchestrator.class); + private final ForwardingPathOperation forwardingPathOperation = mock(ForwardingPathOperation.class); + private final NodeFilterOperation serviceFilterOperation = mock(NodeFilterOperation.class); + private final ToscaFunctionValidator toscaFunctionValidator = mock(ToscaFunctionValidator.class); - private static final UserBusinessLogic userAdminManager = Mockito.mock(UserBusinessLogic.class); - public static final ComponentsUtils componentsUtils = Mockito.mock(ComponentsUtils.class); - public static final IGroupInstanceOperation groupInstanceOperation = Mockito.mock(IGroupInstanceOperation.class); - public static final ToscaOperationFacade toscaOperationFacade = Mockito.mock(ToscaOperationFacade.class); + private static final UserBusinessLogic userAdminManager = mock(UserBusinessLogic.class); + public static final ComponentsUtils componentsUtils = mock(ComponentsUtils.class); + public static final IGroupInstanceOperation groupInstanceOperation = mock(IGroupInstanceOperation.class); + public static final ToscaOperationFacade toscaOperationFacade = mock(ToscaOperationFacade.class); static User adminUser = new User("John", "Doh", USER_ID, "", "ADMIN", null); - private ComponentInstanceBusinessLogic bl = new ComponentInstanceBusinessLogic(elementDao, groupOperation, groupInstanceOperation, + private final ComponentInstanceBusinessLogic bl = new ComponentInstanceBusinessLogic(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation, componentInstanceOperation, artifactBusinessLogic, compInstMergeDataBL, onChangeInstanceOperationOrchestrator, - forwardingPathOperation, serviceFilterOperation, artifactToscaOperation); + forwardingPathOperation, serviceFilterOperation, artifactToscaOperation, toscaFunctionValidator); - @Before - public void setUp() throws Exception { + @BeforeEach + void setUp() throws Exception { MockitoAnnotations.openMocks(this); - Map deploymentResourceArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration().getDeploymentResourceInstanceArtifacts(); + Map deploymentResourceArtifacts = ConfigurationManager.getConfigurationManager().getConfiguration() + .getDeploymentResourceInstanceArtifacts(); Map placeHolderData = (Map) deploymentResourceArtifacts.get(ArtifactsBusinessLogic.HEAT_ENV_NAME); - ArtifactDefinition heatArtifact = getHeatArtifactDefinition(USER_ID, RESOURCE_ID_WITH_HEAT_PARAMS, HEAT_LABEL, ARTIFACT_CREATION_TIME, false, true); + ArtifactDefinition heatArtifact = getHeatArtifactDefinition(USER_ID, RESOURCE_ID_WITH_HEAT_PARAMS, HEAT_LABEL, ARTIFACT_CREATION_TIME, false, + true); Map artifacts = new HashMap<>(); artifacts.put(HEAT_LABEL.toLowerCase(), heatArtifact); Either, StorageOperationStatus> eitherGetResourceArtifact = Either.left(artifacts); - when(artifactBusinessLogic.getArtifacts(RESOURCE_ID_WITH_HEAT_PARAMS, NodeTypeEnum.Resource, ArtifactGroupTypeEnum.DEPLOYMENT, null)).thenReturn(eitherGetResourceArtifact); + when(artifactBusinessLogic.getArtifacts(RESOURCE_ID_WITH_HEAT_PARAMS, NodeTypeEnum.Resource, ArtifactGroupTypeEnum.DEPLOYMENT, + null)).thenReturn(eitherGetResourceArtifact); - ArtifactDefinition heatArtifactNoPayload = getHeatArtifactDefinition(USER_ID, RESOURCE_ID_NO_PAYLOAD, HEAT_LABEL, ARTIFACT_CREATION_TIME, true, false); + ArtifactDefinition heatArtifactNoPayload = getHeatArtifactDefinition(USER_ID, RESOURCE_ID_NO_PAYLOAD, HEAT_LABEL, ARTIFACT_CREATION_TIME, + true, false); Map artifactsNoPayload = new HashMap<>(); artifactsNoPayload.put(HEAT_LABEL.toLowerCase(), heatArtifactNoPayload); Either, StorageOperationStatus> eitherGetResourceArtifactNoPayload = Either.left(artifactsNoPayload); - when(artifactBusinessLogic.getArtifacts(RESOURCE_ID_NO_PAYLOAD, NodeTypeEnum.Resource, ArtifactGroupTypeEnum.DEPLOYMENT, null)).thenReturn(eitherGetResourceArtifactNoPayload); + when(artifactBusinessLogic.getArtifacts(RESOURCE_ID_NO_PAYLOAD, NodeTypeEnum.Resource, ArtifactGroupTypeEnum.DEPLOYMENT, null)).thenReturn( + eitherGetResourceArtifactNoPayload); - ArtifactDefinition heatArtifactNoParams = getHeatArtifactDefinition(USER_ID, RESOURCE_ID_NO_HEAT_PARAMS, HEAT_LABEL, ARTIFACT_CREATION_TIME, false, false); + ArtifactDefinition heatArtifactNoParams = getHeatArtifactDefinition(USER_ID, RESOURCE_ID_NO_HEAT_PARAMS, HEAT_LABEL, ARTIFACT_CREATION_TIME, + false, false); Map artifactsNoParams = new HashMap<>(); artifactsNoParams.put(HEAT_LABEL.toLowerCase(), heatArtifactNoParams); Either, StorageOperationStatus> eitherGetResourceArtifactNoParams = Either.left(artifactsNoParams); - when(artifactBusinessLogic.getArtifacts(RESOURCE_ID_NO_HEAT_PARAMS, NodeTypeEnum.Resource, ArtifactGroupTypeEnum.DEPLOYMENT, null)).thenReturn(eitherGetResourceArtifactNoParams); + when( + artifactBusinessLogic.getArtifacts(RESOURCE_ID_NO_HEAT_PARAMS, NodeTypeEnum.Resource, ArtifactGroupTypeEnum.DEPLOYMENT, null)).thenReturn( + eitherGetResourceArtifactNoParams); ArtifactDefinition eitherPlaceHolder = getArtifactPlaceHolder(RESOURCE_INSTANCE_ID, HEAT_ENV_LABEL); - when(artifactBusinessLogic.createArtifactPlaceHolderInfo(RESOURCE_INSTANCE_ID, HEAT_ENV_LABEL.toLowerCase(), placeHolderData, USER_ID, ArtifactGroupTypeEnum.DEPLOYMENT, false)).thenReturn(eitherPlaceHolder); - - // Mockito.when(artifactBusinessLogic.createArtifactAuditingFields(Mockito.any(ArtifactDefinition.class), Mockito.anyString(), Mockito.anyString())).thenReturn(new EnumMap(AuditingFieldsKey.class)); + when(artifactBusinessLogic.createArtifactPlaceHolderInfo(RESOURCE_INSTANCE_ID, HEAT_ENV_LABEL.toLowerCase(), placeHolderData, USER_ID, + ArtifactGroupTypeEnum.DEPLOYMENT, false)).thenReturn(eitherPlaceHolder); when(userAdminManager.getUser(USER_ID, false)).thenReturn(adminUser); - Mockito.doNothing().when(componentsUtils).auditComponent(any(ResponseFormat.class), any(User.class), any(Component.class), any(AuditingActionEnum.class), + doNothing().when(componentsUtils) + .auditComponent(any(ResponseFormat.class), any(User.class), any(Component.class), any(AuditingActionEnum.class), any(ResourceCommonInfo.class), any(ResourceVersionInfo.class)); - ArtifactDefinition heatEnvEither = getHeatArtifactDefinition(USER_ID, RESOURCE_INSTANCE_ID, HEAT_ENV_LABEL, ARTIFACT_CREATION_TIME, true, false); + ArtifactDefinition heatEnvEither = getHeatArtifactDefinition(USER_ID, RESOURCE_INSTANCE_ID, HEAT_ENV_LABEL, ARTIFACT_CREATION_TIME, true, + false); - when(artifactBusinessLogic.createHeatEnvPlaceHolder(any(ArrayList.class),any(ArtifactDefinition.class), Mockito.anyString(), Mockito.anyString(), any(NodeTypeEnum.class), Mockito.anyString(), any(User.class), - any(Component.class), any())).thenReturn(heatEnvEither); + when(artifactBusinessLogic.createHeatEnvPlaceHolder(any(ArrayList.class), any(ArtifactDefinition.class), anyString(), + anyString(), any(NodeTypeEnum.class), anyString(), any(User.class), + any(Component.class), any())).thenReturn(heatEnvEither); - Either, StorageOperationStatus> groupInstanceEitherLeft = Either.left(new ArrayList<>()); - when(groupInstanceOperation.getAllGroupInstances(Mockito.anyString(), any(NodeTypeEnum.class))).thenReturn(groupInstanceEitherLeft); + Either, StorageOperationStatus> groupInstanceEitherLeft = Either.left(new ArrayList<>()); + when(groupInstanceOperation.getAllGroupInstances(anyString(), any(NodeTypeEnum.class))).thenReturn(groupInstanceEitherLeft); bl.setToscaOperationFacade(toscaOperationFacade); StorageOperationStatus status = StorageOperationStatus.OK; - Mockito.when(toscaOperationFacade.addDeploymentArtifactsToInstance(Mockito.any(String.class), Mockito.any(ComponentInstance.class), Mockito.any(Map.class))).thenReturn(status); - Mockito.when(toscaOperationFacade.addInformationalArtifactsToInstance(Mockito.any(String.class), Mockito.any(ComponentInstance.class), Mockito.any())).thenReturn(status); - Mockito.when(toscaOperationFacade.addGroupInstancesToComponentInstance(Mockito.any(Component.class), Mockito.any(ComponentInstance.class), Mockito.any(), Mockito.any(Map.class))).thenReturn(status); + when(toscaOperationFacade.addDeploymentArtifactsToInstance(any(String.class), any(ComponentInstance.class), + any(Map.class))).thenReturn(status); + when( + toscaOperationFacade.addInformationalArtifactsToInstance(any(String.class), any(ComponentInstance.class), any())) + .thenReturn(status); + when(toscaOperationFacade.addGroupInstancesToComponentInstance(any(Component.class), any(ComponentInstance.class), + any(), any(Map.class))).thenReturn(status); } @Test - public void testAddResourceInstanceArtifacts() throws Exception { + void testAddResourceInstanceArtifacts() { ComponentInstance resourceInstance = new ComponentInstance(); resourceInstance.setName(RESOURCE_INSTANCE_ID); resourceInstance.setComponentUid(RESOURCE_ID_WITH_HEAT_PARAMS); @@ -161,18 +180,17 @@ public class ResourceInstanceBusinessLogicTest extends BaseBusinessLogicMock { Resource originResource = new Resource(); originResource.setUniqueId(RESOURCE_ID_NO_PAYLOAD); ActionStatus addArtifactsRes = bl.addComponentInstanceArtifacts(service, resourceInstance, originResource, adminUser, existingEnvVersions); - assertTrue(addArtifactsRes.equals(ActionStatus.OK)); + assertEquals(ActionStatus.OK, addArtifactsRes); Map deploymentArtifacts = resourceInstance.getDeploymentArtifacts(); assertNotNull(deploymentArtifacts); -// assertTrue(deploymentArtifacts.size() == 2); ArtifactDefinition heatDefinition = deploymentArtifacts.get(HEAT_LABEL.toLowerCase()); assertNotNull(heatDefinition); } - @Test - public void testAddResourceInstanceArtifactsNoParams() throws Exception { + @Test + void testAddResourceInstanceArtifactsNoParams() { ComponentInstance resourceInstance = new ComponentInstance(); resourceInstance.setName(RESOURCE_INSTANCE_ID); resourceInstance.setComponentUid(RESOURCE_ID_NO_HEAT_PARAMS); @@ -183,30 +201,21 @@ public class ResourceInstanceBusinessLogicTest extends BaseBusinessLogicMock { Resource originResource = new Resource(); originResource.setUniqueId(RESOURCE_ID_NO_PAYLOAD); ActionStatus addArtifactsRes = bl.addComponentInstanceArtifacts(service, resourceInstance, originResource, adminUser, existingEnvVersions); - assertTrue(addArtifactsRes.equals(ActionStatus.OK)); + assertEquals(ActionStatus.OK, addArtifactsRes); Map deploymentArtifacts = resourceInstance.getDeploymentArtifacts(); assertNotNull(deploymentArtifacts); -// assertTrue(deploymentArtifacts.size() == 2); ArtifactDefinition heatDefinition = deploymentArtifacts.get(HEAT_LABEL.toLowerCase()); assertNotNull(heatDefinition); -// assertEquals(getHeatArtifactDefinition(USER_ID, RESOURCE_ID_NO_HEAT_PARAMS, HEAT_LABEL, ARTIFACT_CREATION_TIME, false, false), heatDefinition); - -// ArtifactDefinition heatEnvDefinition = deploymentArtifacts.get(HEAT_ENV_LABEL.toLowerCase()); -// assertNotNull(heatEnvDefinition); List heatParameters = heatDefinition.getListHeatParameters(); assertNull(heatParameters); - -// List heatEnvParameters = heatEnvDefinition.getListHeatParameters(); -// assertNull(heatEnvParameters); - } @SuppressWarnings("unchecked") @Test - public void testAddResourceInstanceArtifactsNoArtifacts() throws Exception { + void testAddResourceInstanceArtifactsNoArtifacts() { ComponentInstance resourceInstance = new ComponentInstance(); resourceInstance.setName(RESOURCE_INSTANCE_ID); resourceInstance.setComponentUid(RESOURCE_ID_NO_PAYLOAD); @@ -218,16 +227,18 @@ public class ResourceInstanceBusinessLogicTest extends BaseBusinessLogicMock { originResource.setUniqueId(RESOURCE_ID_NO_PAYLOAD); ActionStatus addArtifactsRes = bl.addComponentInstanceArtifacts(service, resourceInstance, originResource, adminUser, existingEnvVersions); - assertTrue(addArtifactsRes.equals(ActionStatus.OK)); + assertEquals(ActionStatus.OK, addArtifactsRes); Map deploymentArtifacts = resourceInstance.getDeploymentArtifacts(); assertNotNull(deploymentArtifacts); assertEquals(0, deploymentArtifacts.size()); - Mockito.verify(artifactBusinessLogic, Mockito.times(0)).addHeatEnvArtifact(any(ArtifactDefinition.class), any(ArtifactDefinition.class), any(Service.class), any(NodeTypeEnum.class), Mockito.anyString()); + verify(artifactBusinessLogic, never()).addHeatEnvArtifact(any(ArtifactDefinition.class), any(ArtifactDefinition.class), any(Service.class), + any(NodeTypeEnum.class), anyString()); } - private static ArtifactDefinition getHeatArtifactDefinition(String userId, String resourceId, String artifactName, long time, boolean placeholderOnly, boolean withHeatParams) { + private static ArtifactDefinition getHeatArtifactDefinition(String userId, String resourceId, String artifactName, long time, + boolean placeholderOnly, boolean withHeatParams) { ArtifactDefinition artifactInfo = new ArtifactDefinition(); artifactInfo.setArtifactName(artifactName + ".yml"); @@ -238,7 +249,6 @@ public class ResourceInstanceBusinessLogicTest extends BaseBusinessLogicMock { artifactInfo.setUserIdCreator(userId); String fullName = "Jim H"; artifactInfo.setUpdaterFullName(fullName); - // long time = System.currentTimeMillis(); artifactInfo.setCreatorFullName(fullName); artifactInfo.setCreationDate(time); artifactInfo.setLastUpdateDate(time); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/validation/ToscaFunctionValidatorImplTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/validation/ToscaFunctionValidatorImplTest.java new file mode 100644 index 0000000000..3b86d9db78 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/validation/ToscaFunctionValidatorImplTest.java @@ -0,0 +1,498 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl.validation; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import fj.data.Either; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Stream; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; +import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; +import org.openecomp.sdc.be.components.impl.exceptions.ToscaFunctionExceptionSupplier; +import org.openecomp.sdc.be.components.impl.exceptions.ToscaGetFunctionExceptionSupplier; +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; +import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; +import org.openecomp.sdc.common.api.ConfigurationSource; +import org.openecomp.sdc.common.impl.ExternalConfiguration; +import org.openecomp.sdc.common.impl.FSConfigurationSource; + +class ToscaFunctionValidatorImplTest { + + @Mock + private ApplicationDataTypeCache applicationDataTypeCache; + + private ToscaFunctionValidatorImpl toscaFunctionValidator; + + @BeforeAll + static void beforeAll() { + initConfig(); + } + + private static void initConfig() { + final ConfigurationSource configurationSource = new FSConfigurationSource( + ExternalConfiguration.getChangeListener(), + "src/test/resources/config/catalog-be" + ); + new ConfigurationManager(configurationSource); + } + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + toscaFunctionValidator = new ToscaFunctionValidatorImpl(applicationDataTypeCache); + } + + @Test + void testToscaGetFunctionValidation() { + final String containerComponentId = "containerComponentId"; + final String containerComponentName = "containerComponentName"; + final String resourceInstanceId = "resourceInstanceId"; + final String inputName = "myInputToGet"; + final String inputId = String.format("%s.%s", containerComponentId, inputName); + final String schemaType = "string"; + //creating instance list of string property with get_input value + final ComponentInstanceProperty propertyGetInput = new ComponentInstanceProperty(); + propertyGetInput.setName("getInputProperty"); + propertyGetInput.setPropertyId(String.format("%s.%s", containerComponentId, "getInputProperty")); + propertyGetInput.setValue(String.format("get_input: [\"%s\"]", inputName)); + propertyGetInput.setType("list"); + final SchemaDefinition listStringPropertySchema = createSchema(schemaType); + propertyGetInput.setSchema(listStringPropertySchema); + propertyGetInput.setToscaFunction( + createGetToscaFunction(inputName, inputId, List.of(propertyGetInput.getName()), PropertySource.SELF, ToscaGetFunctionType.GET_INPUT, + containerComponentId, containerComponentName) + ); + //creating instance map of string property with get_input value to a second level property: + // get_input: ["property1", "subProperty1", "subProperty2"] + final String getPropertyPropertyName = "getPropertyProperty"; + final List containerPropertyPath = List.of("property1", "subProperty1", "subProperty2"); + final String containerPropertyId = String.format("%s.%s", containerComponentId, containerPropertyPath.get(0)); + final String mapToscaType = "map"; + final ComponentInstanceProperty propertyGetProperty = createComponentInstanceProperty( + String.format("%s.%s", containerComponentId, getPropertyPropertyName), + getPropertyPropertyName, + mapToscaType, + "string", + String.format("\"get_property\": [\"%s\", \"%s\"]", PropertySource.SELF, String.join("\", \"", containerPropertyPath)), + createGetToscaFunction(containerPropertyPath.get(containerPropertyPath.size() - 1), containerPropertyId, + containerPropertyPath, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, containerComponentId, containerComponentName) + ); + + //creating component that has the instance properties + final Component component = new Service(); + component.setUniqueId(containerComponentId); + component.setName(containerComponentName); + //adding instance properties to the component + final List resourceInstanceProperties = List.of(propertyGetInput, propertyGetProperty); + final Map> componentInstanceProps = new HashMap<>(); + componentInstanceProps.put(resourceInstanceId, resourceInstanceProperties); + component.setComponentInstancesProperties(componentInstanceProps); + + //creating component input that will be gotten by the get_input instance property + final var inputDefinition = new InputDefinition(); + inputDefinition.setName(inputName); + inputDefinition.setUniqueId(inputId); + inputDefinition.setType(propertyGetInput.getType()); + inputDefinition.setSchema(listStringPropertySchema); + component.setInputs(List.of(inputDefinition)); + + //creating component property that contains the sub property that will be gotten by the get_property instance property + final var propertyDefinition = new PropertyDefinition(); + propertyDefinition.setName(containerPropertyPath.get(0)); + propertyDefinition.setUniqueId(containerPropertyId); + final String property1Type = "property1.datatype"; + propertyDefinition.setType(property1Type); + component.setProperties(List.of(propertyDefinition)); + //creating resource instance to be added to the component + final ComponentInstance resourceInstance = createComponentInstance("resourceInstance", resourceInstanceId); + component.setComponentInstances(List.of(resourceInstance)); + + //creating data types for "map", and sub properties + final Map allDataTypesMap = new HashMap<>(); + allDataTypesMap.put(mapToscaType, new DataTypeDefinition()); + + final String subProperty1Type = "subProperty1.datatype"; + allDataTypesMap.put(property1Type, createDataType(property1Type, Map.of(containerPropertyPath.get(1), subProperty1Type))); + + final var subProperty2Property = new PropertyDefinition(); + subProperty2Property.setName(containerPropertyPath.get(2)); + subProperty2Property.setType(propertyGetProperty.getType()); + subProperty2Property.setSchema(propertyGetProperty.getSchema()); + allDataTypesMap.put(subProperty1Type, createDataType(subProperty1Type, List.of(subProperty2Property))); + + when(applicationDataTypeCache.getAll(component.getModel())).thenReturn(Either.left(allDataTypesMap)); + //when/then + assertDoesNotThrow(() -> toscaFunctionValidator.validate(propertyGetProperty, component)); + verify(applicationDataTypeCache).getAll(component.getModel()); + } + + @Test + void testToscaGetPropertyOnInstanceValidation() { + final String userId = "userId"; + final String containerComponentId = "containerComponentId"; + final String containerComponentName = "containerComponentName"; + final String instanceUniqueId = String.format("%s.%s", containerComponentId, "instanceId"); + + final List parentPropertyPath = List.of("property1"); + final String containerPropertyId = String.format("%s.%s", containerComponentId, parentPropertyPath.get(0)); + final ComponentInstanceProperty getPropertyOnInstanceProperty = createComponentInstanceProperty( + String.format("%s.%s", containerComponentId, "getPropertyOnInstanceProperty"), + "getPropertyOnInstanceProperty", + "string", + null, + String.format("\"get_property\": [\"%s\", \"%s\"]", PropertySource.INSTANCE, parentPropertyPath.get(0)), + createGetToscaFunction(parentPropertyPath.get(0), containerPropertyId, parentPropertyPath, PropertySource.INSTANCE, + ToscaGetFunctionType.GET_PROPERTY, instanceUniqueId, containerComponentName) + ); + + //creating component that has the instance properties + final Component component = new Service(); + component.setUniqueId(containerComponentId); + component.setName(containerComponentName); + component.setLastUpdaterUserId(userId); + component.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + //adding instance properties to the component + final List resourceInstanceProperties = List.of(getPropertyOnInstanceProperty); + final Map> componentInstanceProps = new HashMap<>(); + componentInstanceProps.put(instanceUniqueId, resourceInstanceProperties); + component.setComponentInstancesProperties(componentInstanceProps); + + //creating resource property that will be get + final var propertyDefinition = new PropertyDefinition(); + propertyDefinition.setName(parentPropertyPath.get(0)); + propertyDefinition.setUniqueId(containerPropertyId); + final String property1Type = "string"; + propertyDefinition.setType(property1Type); + //creating resource instance to be added to the component + final ComponentInstance resourceInstance = createComponentInstance("resourceInstance", instanceUniqueId); + resourceInstance.setProperties(List.of(propertyDefinition)); + component.setComponentInstances(List.of(resourceInstance)); + + assertDoesNotThrow(() -> toscaFunctionValidator.validate(getPropertyOnInstanceProperty, component)); + verify(applicationDataTypeCache, never()).getAll(component.getModel()); + } + + @ParameterizedTest + @MethodSource("getToscaFunctionForValidation") + void validateToscaGetFunctionFailures(final ToscaGetFunctionDataDefinition toscaGetFunction, + final ByActionStatusComponentException expectedException) { + final ComponentInstanceProperty propertyGetInput = new ComponentInstanceProperty(); + propertyGetInput.setName("anyName"); + propertyGetInput.setToscaFunction(toscaGetFunction); + final Component component = new Service(); + final ComponentException actualException = assertThrows(ComponentException.class, + () -> toscaFunctionValidator.validate(propertyGetInput, component)); + assertEquals(expectedException.getActionStatus(), actualException.getActionStatus()); + assertArrayEquals(expectedException.getParams(), actualException.getParams()); + } + + @Test + void validate_propertyNotFoundTest() { + //given + final String containerComponentId = "containerComponentId"; + final String containerComponentName = "containerComponentName"; + final String inputName = "myInputToGet"; + final String inputId = String.format("%s.%s", containerComponentId, inputName); + final String propertyName = "getInputProperty"; + final String propertyId = String.format("%s.%s", containerComponentId, propertyName); + final String propertyType = "string"; + final ComponentInstanceProperty propertyGetInput = createComponentInstanceProperty( + propertyId, + "getInputProperty", + propertyType, + null, + String.format("get_input: [\"%s\"]", inputName), + createGetToscaFunction(inputName, inputId, List.of(propertyName), PropertySource.SELF, ToscaGetFunctionType.GET_INPUT, + containerComponentId, containerComponentName) + ); + + final Component component = new Service(); + final InputDefinition inputDefinition = new InputDefinition(); + inputDefinition.setUniqueId(inputId + "1"); + component.setInputs(List.of(inputDefinition)); + + //when/then + final ByActionStatusComponentException actualException = assertThrows(ByActionStatusComponentException.class, + () -> toscaFunctionValidator.validate(propertyGetInput, component)); + + final ByActionStatusComponentException expectedException = + ToscaGetFunctionExceptionSupplier + .propertyNotFoundOnTarget(inputName, PropertySource.SELF, ToscaGetFunctionType.GET_INPUT) + .get(); + assertEquals(expectedException.getActionStatus(), actualException.getActionStatus()); + assertArrayEquals(expectedException.getParams(), actualException.getParams()); + } + + @Test + void validate_schemaDivergeTest() { + //given + final String containerComponentId = "containerComponentId"; + final String containerComponentName = "containerComponentName"; + final String inputName = "myInputToGet"; + final String inputId = String.format("%s.%s", containerComponentId, inputName); + final String propertyName = "getInputProperty"; + final String propertyId = String.format("%s.%s", containerComponentId, propertyName); + final String propertyType = "list"; + final ComponentInstanceProperty propertyGetInput = createComponentInstanceProperty( + propertyId, + "getInputProperty", + propertyType, + "string", + String.format("get_input: [\"%s\"]", inputName), + createGetToscaFunction(inputName, inputId, List.of(propertyName), PropertySource.SELF, ToscaGetFunctionType.GET_INPUT, + containerComponentId, containerComponentName) + ); + + final Component component = new Service(); + component.setUniqueId(containerComponentId); + component.setName(containerComponentName); + + var inputDefinition = new InputDefinition(); + inputDefinition.setName(inputName); + inputDefinition.setUniqueId(inputId); + inputDefinition.setType(propertyType); + inputDefinition.setSchema(createSchema("integer")); + component.setInputs(List.of(inputDefinition)); + + //when/then + final ByActionStatusComponentException actualException = assertThrows(ByActionStatusComponentException.class, + () -> toscaFunctionValidator.validate(propertyGetInput, component)); + + final ByActionStatusComponentException expectedException = + ToscaGetFunctionExceptionSupplier + .propertySchemaDiverge(propertyGetInput.getToscaFunction().getType(), inputDefinition.getSchemaType(), + propertyGetInput.getSchemaType()) + .get(); + assertEquals(expectedException.getActionStatus(), actualException.getActionStatus()); + assertArrayEquals(expectedException.getParams(), actualException.getParams()); + } + + @Test + void validate_propertyTypeDivergeTest() { + //given + final String containerComponentId = "containerComponentId"; + final String containerComponentName = "containerComponentName"; + final String inputName = "myInputToGet"; + final String inputId = String.format("%s.%s", containerComponentId, inputName); + final String propertyName = "getInputProperty"; + final String propertyId = String.format("%s.%s", containerComponentId, propertyName); + final String propertyType = "string"; + + final ComponentInstanceProperty propertyGetInput = createComponentInstanceProperty( + propertyId, + "getInputProperty", + propertyType, + "string", + String.format("get_input: [\"%s\"]", inputName), + createGetToscaFunction(inputName, inputId, List.of(propertyName), PropertySource.SELF, ToscaGetFunctionType.GET_INPUT, + containerComponentId, containerComponentName) + ); + + final Component component = new Service(); + component.setName(containerComponentName); + component.setUniqueId(containerComponentId); + + var inputDefinition = new InputDefinition(); + inputDefinition.setName(inputName); + inputDefinition.setUniqueId(inputId); + inputDefinition.setType("integer"); + component.setInputs(List.of(inputDefinition)); + + //when/then + final ByActionStatusComponentException actualException = assertThrows(ByActionStatusComponentException.class, + () -> toscaFunctionValidator.validate(propertyGetInput, component)); + + final ByActionStatusComponentException expectedException = + ToscaGetFunctionExceptionSupplier + .propertyTypeDiverge(propertyGetInput.getToscaFunction().getType(), inputDefinition.getType(), propertyGetInput.getType()) + .get(); + assertEquals(expectedException.getActionStatus(), actualException.getActionStatus()); + assertArrayEquals(expectedException.getParams(), actualException.getParams()); + } + + private static Stream getToscaFunctionForValidation() { + final var toscaGetFunction1 = new ToscaGetFunctionDataDefinition(); + final ByActionStatusComponentException expectedResponse1 = ToscaFunctionExceptionSupplier + .missingFunctionType().get(); + + final var toscaGetFunction2 = new ToscaGetFunctionDataDefinition(); + toscaGetFunction2.setFunctionType(ToscaGetFunctionType.GET_INPUT); + final ByActionStatusComponentException expectedResponse2 = ToscaGetFunctionExceptionSupplier + .targetPropertySourceNotFound(toscaGetFunction2.getFunctionType()).get(); + + final var toscaGetFunction3 = new ToscaGetFunctionDataDefinition(); + toscaGetFunction3.setFunctionType(ToscaGetFunctionType.GET_INPUT); + toscaGetFunction3.setPropertySource(PropertySource.SELF); + final ByActionStatusComponentException expectedResponse3 = ToscaGetFunctionExceptionSupplier + .targetSourcePathNotFound(toscaGetFunction3.getFunctionType()).get(); + + final var toscaGetFunction4 = new ToscaGetFunctionDataDefinition(); + toscaGetFunction4.setFunctionType(ToscaGetFunctionType.GET_INPUT); + toscaGetFunction4.setPropertySource(PropertySource.SELF); + toscaGetFunction4.setPropertyPathFromSource(List.of("sourcePath")); + final ByActionStatusComponentException expectedResponse4 = ToscaGetFunctionExceptionSupplier + .sourceNameNotFound(toscaGetFunction4.getPropertySource()).get(); + + final var toscaGetFunction5 = new ToscaGetFunctionDataDefinition(); + toscaGetFunction5.setFunctionType(ToscaGetFunctionType.GET_INPUT); + toscaGetFunction5.setPropertySource(PropertySource.SELF); + toscaGetFunction5.setPropertyPathFromSource(List.of("sourcePath")); + toscaGetFunction5.setSourceName("sourceName"); + final ByActionStatusComponentException expectedResponse5 = ToscaGetFunctionExceptionSupplier + .sourceIdNotFound(toscaGetFunction5.getPropertySource()).get(); + + final var toscaGetFunction6 = new ToscaGetFunctionDataDefinition(); + toscaGetFunction6.setFunctionType(ToscaGetFunctionType.GET_PROPERTY); + toscaGetFunction6.setPropertySource(PropertySource.SELF); + toscaGetFunction6.setPropertyPathFromSource(List.of("sourcePath")); + toscaGetFunction6.setSourceName("sourceName"); + toscaGetFunction6.setSourceUniqueId("sourceUniqueId"); + final ByActionStatusComponentException expectedResponse6 = ToscaGetFunctionExceptionSupplier + .propertyNameNotFound(toscaGetFunction6.getPropertySource()).get(); + + final var toscaGetFunction7 = new ToscaGetFunctionDataDefinition(); + toscaGetFunction7.setFunctionType(ToscaGetFunctionType.GET_PROPERTY); + toscaGetFunction7.setPropertySource(PropertySource.SELF); + toscaGetFunction7.setPropertyPathFromSource(List.of("sourcePath")); + toscaGetFunction7.setSourceName("sourceName"); + toscaGetFunction7.setSourceUniqueId("sourceUniqueId"); + toscaGetFunction7.setPropertyName("propertyName"); + final ByActionStatusComponentException expectedResponse7 = ToscaGetFunctionExceptionSupplier + .propertyIdNotFound(toscaGetFunction7.getPropertySource()).get(); + + return Stream.of( + Arguments.of(toscaGetFunction1, expectedResponse1), + Arguments.of(toscaGetFunction2, expectedResponse2), + Arguments.of(toscaGetFunction3, expectedResponse3), + Arguments.of(toscaGetFunction4, expectedResponse4), + Arguments.of(toscaGetFunction5, expectedResponse5), + Arguments.of(toscaGetFunction6, expectedResponse6), + Arguments.of(toscaGetFunction7, expectedResponse7) + ); + } + + private ComponentInstanceProperty createComponentInstanceProperty(final String uniqueId, final String name, final String type, + final String schemaType, final String value, + final ToscaGetFunctionDataDefinition toscaGetFunction) { + final var componentInstanceProperty = new ComponentInstanceProperty(); + componentInstanceProperty.setName(name); + componentInstanceProperty.setUniqueId(uniqueId); + componentInstanceProperty.setType(type); + componentInstanceProperty.setValue(value); + if (schemaType != null) { + final SchemaDefinition schemaDefinition = createSchema(schemaType); + componentInstanceProperty.setSchema(schemaDefinition); + } + if (toscaGetFunction != null) { + componentInstanceProperty.setToscaFunction(toscaGetFunction); + } + + return componentInstanceProperty; + } + + private SchemaDefinition createSchema(final String schemaType) { + final var schemaDefinition = new SchemaDefinition(); + final var schemaProperty = new PropertyDefinition(); + schemaProperty.setType(schemaType); + schemaDefinition.setProperty(schemaProperty); + return schemaDefinition; + } + + private ToscaGetFunctionDataDefinition createGetToscaFunction(final String propertyName, final String propertyUniqueId, + final List propertyPathFromSource, + final PropertySource propertySource, final ToscaGetFunctionType functionType, + final String sourceUniqueId, + final String sourceName) { + final var toscaGetFunction = new ToscaGetFunctionDataDefinition(); + toscaGetFunction.setFunctionType(functionType); + toscaGetFunction.setPropertyUniqueId(propertyUniqueId); + toscaGetFunction.setPropertyName(propertyName); + toscaGetFunction.setPropertyPathFromSource(propertyPathFromSource); + toscaGetFunction.setPropertySource(propertySource); + toscaGetFunction.setSourceName(sourceName); + toscaGetFunction.setSourceUniqueId(sourceUniqueId); + return toscaGetFunction; + } + + private DataTypeDefinition createDataType(final String name, final Map propertyNameAndTypeMap) { + final var dataTypeDefinition = new DataTypeDefinition(); + dataTypeDefinition.setName(name); + if (MapUtils.isNotEmpty(propertyNameAndTypeMap)) { + for (final Entry propertyEntry : propertyNameAndTypeMap.entrySet()) { + final var propertyDefinition = new PropertyDefinition(); + propertyDefinition.setName(propertyEntry.getKey()); + propertyDefinition.setType(propertyEntry.getValue()); + dataTypeDefinition.setProperties(List.of(propertyDefinition)); + } + } + return dataTypeDefinition; + } + + private DataTypeDefinition createDataType(final String name, final List propertyList) { + final var dataTypeDefinition = new DataTypeDefinition(); + dataTypeDefinition.setName(name); + if (CollectionUtils.isNotEmpty(propertyList)) { + dataTypeDefinition.setProperties(propertyList); + } + return dataTypeDefinition; + } + + private ComponentInstance createComponentInstance(String name, String uniqueId) { + ComponentInstance componentInstance = new ComponentInstance(); + componentInstance.setName(name); + componentInstance.setUniqueId(uniqueId); + return componentInstance; + } + +} \ No newline at end of file diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/GroupEndpointTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/GroupEndpointTest.java index c7886e36eb..8b58702c08 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/GroupEndpointTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/GroupEndpointTest.java @@ -35,6 +35,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import fj.data.Either; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; import javax.ws.rs.client.Entity; @@ -63,6 +64,7 @@ import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupProperty; @@ -191,17 +193,14 @@ class GroupEndpointTest extends JerseySpringBaseTest { when(componentValidations.getComponentInstance(cr, A)).thenReturn(Optional.of(ci)); doNothing().when(groupsOperation) .updateGroupOnComponent(eq(VALID_COMPONENT_ID), isA(GroupDefinition.class), any(PromoteVersionEnum.class)); - when(groupOperation.validateAndUpdatePropertyValue(isA(GroupProperty.class))) + when(groupOperation.validateAndUpdatePropertyValue(any(Component.class), isA(GroupProperty.class))) .thenReturn(StorageOperationStatus.OK); when(groupsOperation .updateGroupPropertiesOnComponent(eq(VALID_COMPONENT_ID), isA(GroupDefinition.class), anyList(), - any(PromoteVersionEnum.class))).thenAnswer(new Answer() { - @Override - public Either answer(InvocationOnMock invocationOnMock) throws Throwable { - Object[] args = invocationOnMock.getArguments(); - return Either.left(Arrays.asList(args[2])); - } - }); + any(PromoteVersionEnum.class))).thenAnswer((Answer) invocationOnMock -> { + Object[] args = invocationOnMock.getArguments(); + return Either.left(Collections.singletonList(args[2])); + }); } @Test -- cgit 1.2.3-korg