diff options
Diffstat (limited to 'catalog-be/src/main')
3 files changed, 286 insertions, 59 deletions
diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml index b539bd0378..99abb7b1ab 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml @@ -2543,7 +2543,7 @@ errors: # %1 - "Model name" DATA_TYPES_NOT_LOADED: { code: 500, - message: "Error: Could not fetch data types from data base with model %1", + message: "Could not fetch data types from data base with model %1", messageId: "SVC4153" } @@ -2660,3 +2660,60 @@ errors: messageId: "SVC4164" } + #---------SVC4165----------------------------- + # %1 - input origin + TOSCA_GET_FUNCTION_INPUTS_ONLY_SELF_ERROR: { + code: 400, + message: "Invalid get_input definition. Inputs can only be get from SELF, the given origin was '%1'", + messageId: "SVC4165" + } + + #---------SVC4166----------------------------- + # %1 - input name + # %2 - input origin + TOSCA_GET_FUNCTION_INPUTS_NOT_FOUND: { + code: 404, + message: "The given input '%1' was not found on '%2'.", + messageId: "SVC4166" + } + + #---------SVC4167----------------------------- + # %1 - Tosca function + # %2 - Referred input type + # %3 - Selected property type + TOSCA_GET_FUNCTION_TYPE_DIVERGE: { + code: 400, + message: "Could not set %1. Referred input type '%2' diverges from the selected property type '%3'.", + messageId: "SVC4167" + } + + #---------SVC4168----------------------------- + # %1 - Tosca function + # %2 - Referred input schema + # %3 - Selected property schema + TOSCA_GET_FUNCTION_SCHEMA_DIVERGE: { + code: 400, + message: "Could not set %1. Referred input schema '%2' diverges from the selected property schema '%3'.", + messageId: "SVC4168" + } + + #---------SVC4169----------------------------- + # %1 - Property type (property|input|attribute) + # %1 - Property name + # %2 - Property origin + TOSCA_GET_FUNCTION_PROPERTY_NOT_FOUND: { + code: 404, + message: "The given %1 '%2' was not found on '%3'.", + messageId: "SVC4169" + } + + #---------SVC4170----------------------------- + # %1 - Property type (property|input|attribute) + # %2 - Property name/path + # %3 - Property data type + TOSCA_GET_FUNCTION_PROPERTY_DATA_TYPE_NOT_FOUND: { + code: 404, + message: "The %1 '%2' type '%3' was not found.", + messageId: "SVC4170" + } + 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 0b284226ee..1fa459da80 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 @@ -43,10 +43,12 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.onap.sdc.tosca.datatypes.model.PropertyType; 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.ToscaGetFunctionExceptionSupplier; import org.openecomp.sdc.be.components.impl.instance.ComponentInstanceChangeOperationOrchestrator; import org.openecomp.sdc.be.components.impl.utils.DirectivesUtil; import org.openecomp.sdc.be.components.merge.instance.ComponentInstanceMergeDataBusinessLogic; @@ -69,9 +71,11 @@ import org.openecomp.sdc.be.datatypes.elements.GetPolicyValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType; import org.openecomp.sdc.be.exception.BusinessException; @@ -167,14 +171,13 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { private static final String RESTRICTED_OPERATION_ON_COMPONENT = "Restricted operation for user: {} on component {}"; private static final String RESOURCE_INSTANCE = "resource instance"; private static final String SERVICE = "service"; - private static final String UPDATE_PROPERTY_CONTEXT = "UpdatePropertyValueOnComponentInstance"; - - private ComponentInstanceOperation componentInstanceOperation; - private ArtifactsBusinessLogic artifactBusinessLogic; - private ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL; - private ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator; - private ForwardingPathOperation forwardingPathOperation; - private NodeFilterOperation nodeFilterOperation; + + private final ComponentInstanceOperation componentInstanceOperation; + private final ArtifactsBusinessLogic artifactBusinessLogic; + private final ComponentInstanceMergeDataBusinessLogic compInstMergeDataBL; + private final ComponentInstanceChangeOperationOrchestrator onChangeInstanceOperationOrchestrator; + private final ForwardingPathOperation forwardingPathOperation; + private final NodeFilterOperation nodeFilterOperation; @Autowired private CompositionBusinessLogic compositionBusinessLogic; @Autowired @@ -1957,7 +1960,11 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { ComponentInstanceProperty componentInstanceProperty = validatePropertyExistsOnComponent(property, containerComponent, foundResourceInstance); String propertyParentUniqueId = property.getParentUniqueId(); - Either<String, ResponseFormat> updatedPropertyValue = updatePropertyObjectValue(property, false, containerComponent.getModel()); + if (property.isGetFunction()) { + validateToscaGetFunction(property, containerComponent); + property.setValue(property.getToscaGetFunction().generatePropertyValue()); + } + Either<String, ResponseFormat> updatedPropertyValue = updatePropertyObjectValue(property, containerComponent.getModel()); if (updatedPropertyValue.isRight()) { log.error("Failed to update property object value of property: {}", property); @@ -2106,7 +2113,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { .get(foundResourceInstance.getUniqueId()); Optional<ComponentInstanceProperty> instanceProperty = instanceProperties.stream().filter(p -> p.getName().equals(property.getName())) .findAny(); - if (!instanceProperty.isPresent()) { + if (instanceProperty.isEmpty()) { throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, property.getName()); } return instanceProperty.get(); @@ -2268,7 +2275,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return false; } - private <T extends PropertyDefinition> Either<String, ResponseFormat> updatePropertyObjectValue(T property, boolean isInput, final String model) { + private <T extends PropertyDefinition> Either<String, ResponseFormat> updatePropertyObjectValue(T property, final String model) { final Map<String, DataTypeDefinition> allDataTypes = componentsUtils.getAllDataTypes(applicationDataTypeCache, model); String innerType = null; String propertyType = property.getType(); @@ -2276,13 +2283,13 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { log.debug("The type of the property {} is {}", property.getUniqueId(), propertyType); if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) { - SchemaDefinition def = property.getSchema(); - if (def == null) { + SchemaDefinition schema = property.getSchema(); + if (schema == null) { log.debug("Schema doesn't exists for property of type {}", type); return Either .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE))); } - PropertyDataDefinition propDef = def.getProperty(); + PropertyDataDefinition propDef = schema.getProperty(); if (propDef == null) { log.debug("Property in Schema Definition inside property of type {} doesn't exist", type); return Either @@ -2294,8 +2301,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { // Specific Update Logic String newValue = property.getValue(); - if (property.getToscaGetFunctionType() != null) { - validateToscaGetFunction(property); + if (property.hasGetFunction()) { return Either.left(newValue); } @@ -2313,14 +2319,12 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { newValue = object.toString(); } } - if (!isInput) { - ImmutablePair<String, Boolean> pair = propertyOperation - .validateAndUpdateRules(propertyType, ((ComponentInstanceProperty) property).getRules(), innerType, allDataTypes, true); - if (pair.getRight() != null && Boolean.FALSE.equals(pair.getRight())) { - BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType); - return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse( - DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)))); - } + ImmutablePair<String, Boolean> pair = propertyOperation + .validateAndUpdateRules(propertyType, ((ComponentInstanceProperty) property).getRules(), innerType, allDataTypes, true); + if (pair.getRight() != null && Boolean.FALSE.equals(pair.getRight())) { + BeEcompErrorManager.getInstance().logBeInvalidValueError("Add property value", pair.getLeft(), property.getName(), propertyType); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse( + DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)))); } return Either.left(newValue); } @@ -2368,29 +2372,96 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return Either.left(newValue); } - private <T extends PropertyDefinition> void validateToscaGetFunction(T property) { - if (property.getToscaGetFunctionType() == ToscaGetFunctionType.GET_INPUT) { - final List<GetInputValueDataDefinition> getInputValues = property.getGetInputValues(); - if (CollectionUtils.isEmpty(getInputValues)) { - log.debug("No input information provided. Cannot set get_input."); - throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT); - } - if (getInputValues.size() > 1) { - log.debug("More than one input provided. Cannot set get_input."); - throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT); - } - final GetInputValueDataDefinition getInputValueDataDefinition = getInputValues.get(0); + private <T extends PropertyDefinition> void validateToscaGetFunction(T property, Component parentComponent) { + final ToscaGetFunctionDataDefinition toscaGetFunction = property.getToscaGetFunction(); + if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_INPUT) { + validateGetFunction(property, parentComponent.getInputs(), parentComponent.getModel()); + return; + } + if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_PROPERTY) { + validateGetFunction(property, parentComponent.getProperties(), parentComponent.getModel()); + return; + } - if (!property.getType().equals(getInputValueDataDefinition.getInputType())) { - log.debug("Input type '{}' diverges from the property type '{}'. Cannot set get_input.", - getInputValueDataDefinition.getInputType(), property.getType()); - throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT); + throw ToscaGetFunctionExceptionSupplier.functionNotSupported(toscaGetFunction.getFunctionType()).get(); + } + + private <T extends PropertyDefinition, U extends PropertyDefinition> void validateGetFunction(final T property, + final List<U> parentProperties, + final String model) { + final ToscaGetFunctionDataDefinition toscaGetFunction = property.getToscaGetFunction(); + if (CollectionUtils.isEmpty(parentProperties)) { + throw ToscaGetFunctionExceptionSupplier + .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource(), + toscaGetFunction.getFunctionType() + ).get(); + } + validateGetPropertySource(toscaGetFunction.getFunctionType(), toscaGetFunction.getPropertySource()); + final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId(); + T referredProperty = (T) 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.getFunctionType(), referredProperty.getType(), property.getType()).get(); + } + if (PropertyType.typeHasSchema(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getSchemaType())) { + throw ToscaGetFunctionExceptionSupplier + .propertySchemaDiverge(toscaGetFunction.getFunctionType(), referredProperty.getSchemaType(), property.getSchemaType()).get(); + } + } + + private <T extends PropertyDefinition> T findSubProperty(final T referredProperty, final ToscaGetFunctionDataDefinition toscaGetFunction, + final String model) { + final Map<String, DataTypeDefinition> dataTypeMap = loadDataTypes(model); + final List<String> propertyPathFromSource = toscaGetFunction.getPropertyPathFromSource(); + DataTypeDefinition dataType = dataTypeMap.get(referredProperty.getType()); + if (dataType == null) { + throw ToscaGetFunctionExceptionSupplier + .propertyDataTypeNotFound(propertyPathFromSource.get(0), referredProperty.getType(), toscaGetFunction.getFunctionType()).get(); + } + T foundProperty = referredProperty; + for (int i = 1; i < propertyPathFromSource.size(); i++) { + final String currentPropertyName = propertyPathFromSource.get(i); + foundProperty = (T) 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; } + return foundProperty; + } + + private Map<String, DataTypeDefinition> loadDataTypes(String model) { + final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypeEither = + applicationDataTypeCache.getAll(model); + if (dataTypeEither.isRight()) { + throw ToscaGetFunctionExceptionSupplier.couldNotLoadDataTypes(model).get(); + } + return dataTypeEither.left().value(); + } - throw new ByActionStatusComponentException(ActionStatus.NOT_SUPPORTED, - "Tosca function " + property.getToscaGetFunctionType().getToscaGetFunctionName()); + private void validateGetPropertySource(final ToscaGetFunctionType functionType, final PropertySource propertySource) { + if (propertySource != PropertySource.SELF) { + throw ToscaGetFunctionExceptionSupplier + .targetSourceNotSupported(functionType, propertySource).get(); + } } private ResponseFormat updateInputOnContainerComponent(ComponentInstanceInput input, String newValue, Component containerComponent, @@ -3054,22 +3125,18 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return ComponentValidations.validateNameIsUniqueInComponent(oldComponentInstance.getName(), newInstanceName, containerComponent); } - private Either<ComponentInstance, StorageOperationStatus> getResourceInstanceById(Component containerComponent, String instanceId) { - Either<ComponentInstance, StorageOperationStatus> result = Either.right(StorageOperationStatus.NOT_FOUND); - List<ComponentInstance> instances = containerComponent.getComponentInstances(); - Optional<ComponentInstance> foundInstance = Optional.empty(); - if (!CollectionUtils.isEmpty(instances)) { - if (result.isRight()) { - foundInstance = instances.stream().filter(i -> i.getUniqueId().equals(instanceId)).findFirst(); - if (!foundInstance.isPresent()) { - result = Either.right(StorageOperationStatus.NOT_FOUND); - } - } - if (result.isRight() && foundInstance.isPresent()) { - result = Either.left(foundInstance.get()); - } + private Either<ComponentInstance, StorageOperationStatus> getResourceInstanceById(final Component containerComponent, final String instanceId) { + final List<ComponentInstance> instances = containerComponent.getComponentInstances(); + if (CollectionUtils.isEmpty(instances)) { + return Either.right(StorageOperationStatus.NOT_FOUND); } - return result; + + final Optional<ComponentInstance> foundInstance = instances.stream().filter(i -> i.getUniqueId().equals(instanceId)).findFirst(); + if (foundInstance.isEmpty()) { + return Either.right(StorageOperationStatus.NOT_FOUND); + } + + return Either.left(foundInstance.get()); } private ComponentInstance buildComponentInstance(ComponentInstance resourceInstanceForUpdate, ComponentInstance origInstanceForUpdate) { @@ -3726,4 +3793,13 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { final User user = userValidations.validateUserExists(userId); userValidations.validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN)); } + + public void setCompositionBusinessLogic(CompositionBusinessLogic compositionBusinessLogic) { + this.compositionBusinessLogic = compositionBusinessLogic; + } + + public void setContainerInstanceTypesData(ContainerInstanceTypesData containerInstanceTypesData) { + this.containerInstanceTypesData = containerInstanceTypesData; + } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java new file mode 100644 index 0000000000..d54cb79ba5 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java @@ -0,0 +1,94 @@ +/* + * - + * ============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.exceptions; + +import java.util.List; +import java.util.function.Supplier; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.enums.PropertySource; +import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ToscaGetFunctionExceptionSupplier { + + public static Supplier<ByActionStatusComponentException> targetSourceNotSupported(final ToscaGetFunctionType toscaGetFunctionType, + final PropertySource propertySource) { + final String errorMsg = String.format("%s on %s", toscaGetFunctionType.getFunctionName(), propertySource.getName()); + return () -> new ByActionStatusComponentException(ActionStatus.NOT_SUPPORTED, errorMsg); + } + + public static Supplier<ByActionStatusComponentException> propertyNotFoundOnTarget(final String propertyName, + final PropertySource propertySource, + final ToscaGetFunctionType functionType) { + return propertyNotFoundOnTarget(List.of(propertyName), propertySource, functionType); + } + + public static Supplier<ByActionStatusComponentException> propertyNotFoundOnTarget(final List<String> propertyPathFromSource, + final PropertySource propertySource, + final ToscaGetFunctionType functionType) { + return () -> new ByActionStatusComponentException(ActionStatus.TOSCA_GET_FUNCTION_PROPERTY_NOT_FOUND, functionType.getPropertyType(), + String.join("->", propertyPathFromSource), propertySource.getName()); + } + + public static Supplier<ByActionStatusComponentException> propertyDataTypeNotFound(final String propertyName, + final String dataType, + final ToscaGetFunctionType functionType) { + return propertyDataTypeNotFound(List.of(propertyName), dataType, functionType); + } + + public static Supplier<ByActionStatusComponentException> propertyDataTypeNotFound(final List<String> propertyPathFromSource, + final String dataType, + final ToscaGetFunctionType functionType) { + return () -> new ByActionStatusComponentException( + ActionStatus.TOSCA_GET_FUNCTION_PROPERTY_DATA_TYPE_NOT_FOUND, + functionType.getPropertyType(), String.join("->", propertyPathFromSource), dataType + ); + } + + public static Supplier<ByActionStatusComponentException> couldNotLoadDataTypes(final String model) { + return () -> new ByActionStatusComponentException(ActionStatus.DATA_TYPES_NOT_LOADED, model); + } + + public static Supplier<ByActionStatusComponentException> functionNotSupported(final ToscaGetFunctionType functionType) { + return () -> new ByActionStatusComponentException(ActionStatus.NOT_SUPPORTED, "Tosca function " + functionType.getFunctionName()); + } + + public static Supplier<ByActionStatusComponentException> propertyTypeDiverge(final ToscaGetFunctionType functionType, + final String referredPropertyType, + final String propertyType) { + return () -> new ByActionStatusComponentException( + ActionStatus.TOSCA_GET_FUNCTION_TYPE_DIVERGE, + functionType.getFunctionName(), referredPropertyType, propertyType + ); + } + + public static Supplier<ByActionStatusComponentException> propertySchemaDiverge(final ToscaGetFunctionType functionType, + final String referredPropertySchemaType, + final String propertySchemaType) { + return () -> new ByActionStatusComponentException( + ActionStatus.TOSCA_GET_FUNCTION_SCHEMA_DIVERGE, + functionType.getFunctionName(), referredPropertySchemaType, propertySchemaType + ); + } +} |