*/
package org.openecomp.sdc.be.components.impl;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
import fj.data.Either;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
+import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
import org.openecomp.sdc.be.components.validation.ComponentValidations;
import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil;
import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.model.ArtifactTypeDefinition;
import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.model.ComponentInstance;
import org.openecomp.sdc.be.model.ComponentInstanceInterface;
import org.openecomp.sdc.be.model.ComponentParametersView;
import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.PropertyConstraint;
+import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.model.User;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
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.InterfaceLifecycleOperation;
+import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
+import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
import org.openecomp.sdc.be.user.Role;
import org.openecomp.sdc.common.datastructure.Wrapper;
import org.openecomp.sdc.exception.ResponseFormat;
public class ComponentInterfaceOperationBusinessLogic extends BaseBusinessLogic {
private static final Logger LOGGER = LoggerFactory.getLogger(ComponentInterfaceOperationBusinessLogic.class);
+ private static final String UPDATE_INTERFACE_OPERATION_ON_COMPONENT_INSTANCE =
+ "Update Interface Operation on Component instance";
+ private static final String EXCEPTION_OCCURRED_WHEN_UPDATING_COMPONENT_INSTANCE_INTERFACES =
+ "Exception occurred when updating Component Instance Interfaces {}";
private final ComponentValidations componentValidations;
+ private final PropertyBusinessLogic propertyBusinessLogic;
+ private final ArtifactTypeBusinessLogic artifactTypeBusinessLogic;
@Autowired
public ComponentInterfaceOperationBusinessLogic(final IElementOperation elementDao, final IGroupOperation groupOperation,
final IGroupTypeOperation groupTypeOperation, final InterfaceOperation interfaceOperation,
final InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
final ArtifactsOperations artifactToscaOperation,
- final ComponentValidations componentValidations) {
+ final ComponentValidations componentValidations,
+ final PropertyBusinessLogic propertyBusinessLogic,
+ final ArtifactTypeBusinessLogic artifactTypeBusinessLogic) {
super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
artifactToscaOperation);
this.componentValidations = componentValidations;
+ this.propertyBusinessLogic = propertyBusinessLogic;
+ this.artifactTypeBusinessLogic = artifactTypeBusinessLogic;
}
public Optional<ComponentInstance> updateComponentInstanceInterfaceOperation(final String componentId, final String componentInstanceId,
errorWrapper.setInnerElement(responseFormat);
return Optional.empty();
}
+
+ final String model = propertyBusinessLogic.getComponentModelByComponentId(componentId);
+ PropertyValueConstraintValidationUtil constraintValidatorUtil = new PropertyValueConstraintValidationUtil();
+ Either<Boolean, ResponseFormat> constraintValidatorResponse =
+ validateOperationInputConstraints(updatedOperationDataDefinition, constraintValidatorUtil, model);
+ if (!isConstraintsValidationSucceed(constraintValidatorResponse, errorWrapper, updatedOperationDataDefinition)) {
+ return Optional.empty();
+ }
+ constraintValidatorResponse = validateOperationArtifactPropertyConstraints(
+ updatedOperationDataDefinition, constraintValidatorUtil, model);
+ if (!isConstraintsValidationSucceed(constraintValidatorResponse, errorWrapper, updatedOperationDataDefinition)) {
+ return Optional.empty();
+ }
+
updateOperationDefinitionImplementation(updatedOperationDataDefinition);
optionalComponentInstanceInterface.get().getOperations().replace(updatedOperationDataDefinition.getName(), updatedOperationDataDefinition);
boolean wasLocked = false;
try {
if (shouldLock) {
- lockComponent(componentId, component, "Update Interface Operation on Component instance");
+ lockComponent(componentId, component, UPDATE_INTERFACE_OPERATION_ON_COMPONENT_INSTANCE);
wasLocked = true;
}
final StorageOperationStatus status = toscaOperationFacade.updateComponentInstanceInterfaces(component, componentInstanceId);
if (status != StorageOperationStatus.OK) {
janusGraphDao.rollback();
responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
- LOGGER.error("Exception occurred when updating Component Instance Interfaces {}", responseFormat);
+ LOGGER.error(EXCEPTION_OCCURRED_WHEN_UPDATING_COMPONENT_INSTANCE_INTERFACES, responseFormat);
errorWrapper.setInnerElement(responseFormat);
return Optional.empty();
}
return componentInstanceOptional;
}
+ private Either<Boolean, ResponseFormat> validateOperationInputConstraints (
+ OperationDataDefinition operationDataDefinition, PropertyValueConstraintValidationUtil constraintValidatorUtil, String model) {
+ return constraintValidatorUtil
+ .validatePropertyConstraints(convertOperationInputsToPropertyDefinitions(operationDataDefinition), applicationDataTypeCache,
+ model);
+ }
+
+ private Either<Boolean, ResponseFormat> validateOperationArtifactPropertyConstraints (
+ OperationDataDefinition operationDataDefinition, PropertyValueConstraintValidationUtil constraintValidatorUtil, String model) {
+ return constraintValidatorUtil
+ .validatePropertyConstraints(convertOperationArtifactPropsToPropertyDefinitions(operationDataDefinition, model), applicationDataTypeCache,
+ model);
+ }
+
+ private boolean isConstraintsValidationSucceed(Either<Boolean, ResponseFormat> constraintValidatorResponse,
+ Wrapper<ResponseFormat> errorWrapper,
+ OperationDataDefinition updatedOperationDataDefinition) {
+ if (constraintValidatorResponse.isRight()) {
+ ResponseFormat responseFormat = constraintValidatorResponse.right().value();
+ LOGGER.error("Failed constraints validation on inputs for interface operation: {} - {}",
+ updatedOperationDataDefinition.getName(),
+ constraintValidatorResponse.right().value());
+ errorWrapper.setInnerElement(responseFormat);
+ return false;
+ }
+ return true;
+ }
+
public Optional<Component> updateResourceInterfaceOperation(final String componentId,
final String user,
final InterfaceDefinition interfaceDefinition,
boolean wasLocked = false;
try {
if (shouldLock) {
- lockComponent(componentId, component, "Update Interface Operation on Component instance");
+ lockComponent(componentId, component, UPDATE_INTERFACE_OPERATION_ON_COMPONENT_INSTANCE);
wasLocked = true;
}
final StorageOperationStatus status = toscaOperationFacade.updateComponentInterfaces(component, interfaceDefinitionType);
if (status != StorageOperationStatus.OK) {
janusGraphDao.rollback();
responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
- LOGGER.error("Exception occurred when updating Component Instance Interfaces {}", responseFormat);
+ LOGGER.error(EXCEPTION_OCCURRED_WHEN_UPDATING_COMPONENT_INSTANCE_INTERFACES, responseFormat);
errorWrapper.setInnerElement(responseFormat);
return Optional.empty();
}
boolean wasLocked = false;
try {
if (shouldLock) {
- lockComponent(componentId, component, "Update Interface Operation on Component instance");
+ lockComponent(componentId, component, UPDATE_INTERFACE_OPERATION_ON_COMPONENT_INSTANCE);
wasLocked = true;
}
final Either<InterfaceDefinition, StorageOperationStatus> operationStatusEither =
if (operationStatusEither.isRight()) {
janusGraphDao.rollback();
responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
- LOGGER.error("Exception occurred when updating Component Instance Interfaces {}", responseFormat);
+ LOGGER.error(EXCEPTION_OCCURRED_WHEN_UPDATING_COMPONENT_INSTANCE_INTERFACES, responseFormat);
errorWrapper.setInnerElement(responseFormat);
return Optional.empty();
}
artifactInfo.setArtifactName(String.format("'%s'", updatedOperationDataDefinition.getImplementation().getArtifactName()));
updatedOperationDataDefinition.setImplementation(artifactInfo);
}
+
+ private List<PropertyDefinition> convertOperationInputsToPropertyDefinitions(final OperationDataDefinition operationDataDefinition) {
+ List<PropertyDefinition> propertyDefinitions = new ArrayList<>();
+ ListDataDefinition<OperationInputDefinition> inputsDefinitionListData = operationDataDefinition.getInputs();
+ if (null != inputsDefinitionListData && !inputsDefinitionListData.isEmpty()) {
+ List<OperationInputDefinition> inputDefinitionList =
+ inputsDefinitionListData.getListToscaDataDefinition();
+ for (OperationInputDefinition operationInputDefinition : inputDefinitionList) {
+ PropertyDefinition propertyDefinition = new PropertyDefinition();
+ propertyDefinition.setValue(operationInputDefinition.getValue());
+ propertyDefinition.setType(operationInputDefinition.getType());
+ propertyDefinition.setName(operationInputDefinition.getName());
+ propertyDefinition.setDefaultValue(operationInputDefinition.getDefaultValue());
+ propertyDefinition.setInputPath(operationInputDefinition.getInputPath());
+ propertyDefinitions.add(propertyDefinition);
+ }
+ }
+ return propertyDefinitions;
+ }
+
+ private List<PropertyDefinition> convertOperationArtifactPropsToPropertyDefinitions(final OperationDataDefinition operationDataDefinition,
+ final String model) {
+ List<PropertyDefinition> artifactPropertiesToValidateCollection = new ArrayList<>();
+ final ArtifactDataDefinition artifactDataDefinition = operationDataDefinition.getImplementation();
+ if (null != artifactDataDefinition) {
+ final String artifactType = artifactDataDefinition.getArtifactType();
+ final String uniqueId = UniqueIdBuilder.buildArtifactTypeUid(model, artifactType);
+ ArtifactTypeDefinition retrievedArtifact = artifactTypeBusinessLogic.getArtifactTypeByUid(uniqueId);
+ if (retrievedArtifact != null) {
+ List<PropertyDataDefinition> artifactPropertiesList = artifactDataDefinition.getProperties();
+ if (null != artifactPropertiesList && !artifactPropertiesList.isEmpty()) {
+ for (PropertyDataDefinition propertyDataDefinition : artifactPropertiesList) {
+ PropertyDefinition propertyDefinition = new PropertyDefinition();
+ propertyDefinition.setConstraints(deserializePropertyConstraints(propertyDataDefinition.getPropertyConstraints()));
+ propertyDefinition.setValue(propertyDataDefinition.getValue());
+ propertyDefinition.setType(propertyDataDefinition.getType());
+ propertyDefinition.setName(propertyDataDefinition.getName());
+ propertyDefinition.setDefaultValue(propertyDataDefinition.getDefaultValue());
+ propertyDefinition.setInputPath(propertyDataDefinition.getInputPath());
+ artifactPropertiesToValidateCollection.add(propertyDefinition);
+ }
+ }
+ }
+ }
+ return artifactPropertiesToValidateCollection;
+ }
+
+ private List<PropertyConstraint> deserializePropertyConstraints(List<String> constraints) {
+ if (CollectionUtils.isNotEmpty(constraints)) {
+ Type constraintType = new TypeToken<PropertyConstraint>() {
+ }.getType();
+ Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyOperation.PropertyConstraintDeserialiser()).create();
+ return constraints.stream().map(c -> (PropertyConstraint) gson.fromJson(c, constraintType)).collect(
+ Collectors.toList());
+ }
+ return null;
+ }
}
package org.openecomp.sdc.be.components.impl;
import static org.assertj.core.api.Assertions.assertThat;
+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.Mockito.when;
import fj.data.Either;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
import org.openecomp.sdc.be.components.validation.ComponentValidations;
import org.openecomp.sdc.be.components.validation.UserValidations;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
-import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.ArtifactTypeDefinition;
import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.model.ComponentInstance;
import org.openecomp.sdc.be.model.ComponentInstanceInterface;
import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.PropertyConstraint;
+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.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
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.UniqueIdBuilder;
+import org.openecomp.sdc.be.model.tosca.constraints.ValidValuesConstraint;
import org.openecomp.sdc.common.datastructure.Wrapper;
+import org.openecomp.sdc.exception.ResponseFormat;
@ExtendWith(MockitoExtension.class)
-public class ComponentInterfaceOperationBusinessLogicTest extends BaseBusinessLogicMock {
+class ComponentInterfaceOperationBusinessLogicTest extends BaseBusinessLogicMock {
@InjectMocks
private ComponentInterfaceOperationBusinessLogic componentInterfaceOperationBusinessLogic;
private UserValidations userValidations;
@Mock
private ComponentValidations componentValidations;
+ @Mock
+ private PropertyBusinessLogic propertyBusinessLogic;
+ @Mock
+ private ApplicationDataTypeCache applicationDataTypeCache;
+ @Mock
+ private ArtifactTypeBusinessLogic artifactTypeBusinessLogic;
private Component component;
private ComponentInstance componentInstance;
componentInterfaceOperationBusinessLogic =
new ComponentInterfaceOperationBusinessLogic(elementDao, groupOperation, groupInstanceOperation,
groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation,
- componentValidations);
+ componentValidations, propertyBusinessLogic, artifactTypeBusinessLogic);
componentInterfaceOperationBusinessLogic.setToscaOperationFacade(toscaOperationFacade);
componentInterfaceOperationBusinessLogic.setGraphLockOperation(graphLockOperation);
componentInterfaceOperationBusinessLogic.setComponentsUtils(componentsUtils);
componentInterfaceOperationBusinessLogic.setUserValidations(userValidations);
componentInterfaceOperationBusinessLogic.setJanusGraphGenericDao(janusGraphGenericDao);
componentInterfaceOperationBusinessLogic.setJanusGraphDao(janusGraphDao);
-
+ componentInterfaceOperationBusinessLogic.setApplicationDataTypeCache(applicationDataTypeCache);
initComponentData();
}
@Test
- public void updateSubstitutionFilterTest() throws BusinessLogicException {
+ void updateComponentInstanceInterfaceOperationTest() throws BusinessLogicException {
final String componentId = component.getUniqueId();
final String componentInstanceId = componentInstance.getUniqueId();
final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
when(janusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK);
when(graphLockOperation.unlockComponent(componentId, NodeTypeEnum.Service))
.thenReturn(StorageOperationStatus.OK);
+ when(applicationDataTypeCache.getAll(null)).thenReturn(Either.left(new HashMap<>()));
final Optional<ComponentInstance> result = componentInterfaceOperationBusinessLogic
.updateComponentInstanceInterfaceOperation(componentId, componentInstanceId, interfaceDefinition,
assertThat(result).isPresent();
}
- public void initComponentData() {
+ @Test
+ void valueForInputFailsConstraintsValidation() throws BusinessLogicException {
+ final String inputType = "myType";
+ final String componentId = component.getUniqueId();
+ final String componentInstanceId = componentInstance.getUniqueId();
+ final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
+ interfaceDefinition.setUniqueId(UUID.randomUUID().toString());
+ interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard");
+ final Map<String, OperationDataDefinition> operations = new HashMap<>();
+ final OperationDataDefinition operationDataDefinition = new OperationDataDefinition();
+ operationDataDefinition.setUniqueId(UUID.randomUUID().toString());
+ final ArtifactDataDefinition artifactDataDefinition = new ArtifactDataDefinition();
+ final ListDataDefinition<OperationInputDefinition> inputsDefinitionListData = new ListDataDefinition<>();
+ OperationInputDefinition input1 = new OperationInputDefinition();
+ input1.setName("input_1");
+ input1.setType(inputType);
+ input1.setValue("{\"input_range\": \"invalid\"}");
+ inputsDefinitionListData.add(input1);
+ artifactDataDefinition.setArtifactName("EO Implementation info");
+ operationDataDefinition.setImplementation(artifactDataDefinition);
+ operationDataDefinition.setInputs(inputsDefinitionListData);
+ operations.put("configure", operationDataDefinition);
+ interfaceDefinition.setOperations(operations );
+
+ DataTypeDefinition myType = new DataTypeDefinition();
+ myType.setName(inputType);
+ PropertyDefinition input_range = new PropertyDefinition();
+ input_range.setName("input_range");
+ input_range.setType("string");
+ PropertyConstraint constraint1 = new ValidValuesConstraint(Arrays.asList("value1", "value2", "value3"));
+ input_range.setConstraints(List.of(constraint1));
+ myType.setProperties(List.of(input_range));
+ Map<String, DataTypeDefinition> dataTypes = Collections.singletonMap(myType.getName(), myType);
+ Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
+
+ final ComponentInstanceInterface componentInstanceInterface =
+ new ComponentInstanceInterface("interfaceId", interfaceDefinition);
+ Map<String, List<ComponentInstanceInterface>> componentInstancesInterfacesMap = new HashMap<>();
+ componentInstancesInterfacesMap.put(componentInstanceId, Collections.singletonList(componentInstanceInterface));
+ component.setComponentInstancesInterfaces(componentInstancesInterfacesMap);
+ componentInstance.setInterfaces(
+ (Map<String, Object>) new HashMap<>().put(componentInstanceId, interfaceDefinition));
+ component.setComponentInstances(Collections.singletonList(componentInstance));
+
+ when(toscaOperationFacade.getToscaElement(componentId)).thenReturn(Either.left(component));
+ when(componentValidations.getComponentInstance(component, componentInstanceId))
+ .thenReturn(Optional.of(componentInstance));
+ when(applicationDataTypeCache.getAll(null)).thenReturn(Either.left(dataTypes));
+
+ final Optional<ComponentInstance> result = componentInterfaceOperationBusinessLogic
+ .updateComponentInstanceInterfaceOperation(componentId, componentInstanceId, interfaceDefinition,
+ ComponentTypeEnum.SERVICE, errorWrapper, false);
+ assertThat(result).isNotPresent();
+ assertTrue(errorWrapper.getInnerElement().getStatus() == 400);
+ assertTrue(errorWrapper.getInnerElement().getRequestError().getRequestError().getServiceException().getText()
+ .contains("Error: Invalid property values provided"));
+ }
+
+ @Test
+ void valueForInputSucceedsConstraintsValidation() throws BusinessLogicException {
+ final String inputType = "myType";
+ final String componentId = component.getUniqueId();
+ final String componentInstanceId = componentInstance.getUniqueId();
+ final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
+ interfaceDefinition.setUniqueId(UUID.randomUUID().toString());
+ interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard");
+ final Map<String, OperationDataDefinition> operations = new HashMap<>();
+ final OperationDataDefinition operationDataDefinition = new OperationDataDefinition();
+ operationDataDefinition.setUniqueId(UUID.randomUUID().toString());
+ final ArtifactDataDefinition artifactDataDefinition = new ArtifactDataDefinition();
+ final ListDataDefinition<OperationInputDefinition> inputsDefinitionListData = new ListDataDefinition<>();
+ OperationInputDefinition input1 = new OperationInputDefinition();
+ input1.setName("input_1");
+ input1.setType(inputType);
+ input1.setValue("{\"input_range\": \"value1\"}");
+ inputsDefinitionListData.add(input1);
+ artifactDataDefinition.setArtifactName("EO Implementation info");
+ operationDataDefinition.setImplementation(artifactDataDefinition);
+ operationDataDefinition.setInputs(inputsDefinitionListData);
+ operations.put("configure", operationDataDefinition);
+ interfaceDefinition.setOperations(operations );
+
+ DataTypeDefinition myType = new DataTypeDefinition();
+ myType.setName(inputType);
+ PropertyDefinition input_range = new PropertyDefinition();
+ input_range.setName("input_range");
+ input_range.setType("string");
+ PropertyConstraint constraint1 = new ValidValuesConstraint(Arrays.asList("value1", "value2", "value3"));
+ input_range.setConstraints(List.of(constraint1));
+ myType.setProperties(List.of(input_range));
+ Map<String, DataTypeDefinition> dataTypes = Collections.singletonMap(myType.getName(), myType);
+ Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
+
+ final ComponentInstanceInterface componentInstanceInterface =
+ new ComponentInstanceInterface("interfaceId", interfaceDefinition);
+ Map<String, List<ComponentInstanceInterface>> componentInstancesInterfacesMap = new HashMap<>();
+ componentInstancesInterfacesMap.put(componentInstanceId, Collections.singletonList(componentInstanceInterface));
+ component.setComponentInstancesInterfaces(componentInstancesInterfacesMap);
+ componentInstance.setInterfaces(
+ (Map<String, Object>) new HashMap<>().put(componentInstanceId, interfaceDefinition));
+ component.setComponentInstances(Collections.singletonList(componentInstance));
+
+ when(toscaOperationFacade.getToscaElement(componentId)).thenReturn(Either.left(component));
+ when(componentValidations.getComponentInstance(component, componentInstanceId))
+ .thenReturn(Optional.of(componentInstance));
+ when(toscaOperationFacade.updateComponentInstanceInterfaces(component, componentInstanceId))
+ .thenReturn(StorageOperationStatus.OK);
+ when(toscaOperationFacade
+ .updateComponentInstanceMetadataOfTopologyTemplate(any(Service.class), any(ComponentParametersView.class)))
+ .thenReturn(Either.left(component));
+ when(applicationDataTypeCache.getAll(null)).thenReturn(Either.left(dataTypes));
+
+ final Optional<ComponentInstance> result = componentInterfaceOperationBusinessLogic
+ .updateComponentInstanceInterfaceOperation(componentId, componentInstanceId, interfaceDefinition,
+ ComponentTypeEnum.SERVICE, errorWrapper, false);
+ assertThat(result).isPresent();
+ }
+
+ @Test
+ void valueForArtifactInputFailsConstraintsValidation() throws BusinessLogicException {
+ final String inputType = "myType";
+ final String artifactType = "artifactType";
+ final String componentId = component.getUniqueId();
+ final String componentInstanceId = componentInstance.getUniqueId();
+ final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
+ interfaceDefinition.setUniqueId(UUID.randomUUID().toString());
+ interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard");
+ final Map<String, OperationDataDefinition> operations = new HashMap<>();
+ final OperationDataDefinition operationDataDefinition = new OperationDataDefinition();
+ operationDataDefinition.setUniqueId(UUID.randomUUID().toString());
+ final ArtifactDataDefinition artifactDataDefinition = new ArtifactDataDefinition();
+
+ artifactDataDefinition.setArtifactName("EO Implementation info");
+ artifactDataDefinition.setArtifactType(artifactType);
+ PropertyDataDefinition propertyDataDefinition = new PropertyDataDefinition();
+ propertyDataDefinition.setName("propertyWithRestrictedValues");
+ propertyDataDefinition.setType(inputType);
+ propertyDataDefinition.setValue("{\"propertyWithRestrictedValues\": \"invalid\"}");
+ artifactDataDefinition.addProperty(propertyDataDefinition);
+
+ operationDataDefinition.setImplementation(artifactDataDefinition);
+ operations.put("configure", operationDataDefinition);
+ interfaceDefinition.setOperations(operations );
+
+ final DataTypeDefinition myType = new DataTypeDefinition();
+ final ArtifactTypeDefinition artifactTypeDefinitionFromCache = new ArtifactTypeDefinition();
+ artifactTypeDefinitionFromCache.setName(UniqueIdBuilder.buildArtifactTypeUid(null, artifactType));
+ myType.setName(inputType);
+ PropertyDefinition propertyWithRestrictedValues = new PropertyDefinition();
+ propertyWithRestrictedValues.setName("propertyWithRestrictedValues");
+ propertyWithRestrictedValues.setType("string");
+ PropertyConstraint constraint1 = new ValidValuesConstraint(Arrays.asList("value1", "value2", "value3"));
+ propertyWithRestrictedValues.setConstraints(List.of(constraint1));
+ artifactTypeDefinitionFromCache.setProperties(List.of(propertyWithRestrictedValues));
+ myType.setProperties(List.of(propertyWithRestrictedValues));
+ Map<String, DataTypeDefinition> dataTypes = Collections.singletonMap(myType.getName(), myType);
+ Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
+
+ final ComponentInstanceInterface componentInstanceInterface =
+ new ComponentInstanceInterface("interfaceId", interfaceDefinition);
+ Map<String, List<ComponentInstanceInterface>> componentInstancesInterfacesMap = new HashMap<>();
+ componentInstancesInterfacesMap.put(componentInstanceId, Collections.singletonList(componentInstanceInterface));
+ component.setComponentInstancesInterfaces(componentInstancesInterfacesMap);
+ componentInstance.setInterfaces(
+ (Map<String, Object>) new HashMap<>().put(componentInstanceId, interfaceDefinition));
+ component.setComponentInstances(Collections.singletonList(componentInstance));
+
+ when(toscaOperationFacade.getToscaElement(componentId)).thenReturn(Either.left(component));
+ when(componentValidations.getComponentInstance(component, componentInstanceId))
+ .thenReturn(Optional.of(componentInstance));
+ when(applicationDataTypeCache.getAll(null)).thenReturn(Either.left(dataTypes));
+ when(artifactTypeBusinessLogic.getArtifactTypeByUid(UniqueIdBuilder.buildArtifactTypeUid(
+ null, artifactType))).thenReturn(artifactTypeDefinitionFromCache);
+
+ final Optional<ComponentInstance> result = componentInterfaceOperationBusinessLogic
+ .updateComponentInstanceInterfaceOperation(componentId, componentInstanceId, interfaceDefinition,
+ ComponentTypeEnum.SERVICE, errorWrapper, false);
+ assertThat(result).isNotPresent();
+ assertTrue(errorWrapper.getInnerElement().getStatus() == 400);
+ assertTrue(errorWrapper.getInnerElement().getRequestError().getRequestError().getServiceException().getText()
+ .contains("Error: Invalid property values provided"));
+ }
+
+ @Test
+ void valueForArtifactInputSucceedsConstraintsValidation() throws BusinessLogicException {
+ final String inputType = "myType";
+ final String artifactType = "artifactType";
+ final String componentId = component.getUniqueId();
+ final String componentInstanceId = componentInstance.getUniqueId();
+ final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
+ interfaceDefinition.setUniqueId(UUID.randomUUID().toString());
+ interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard");
+ final Map<String, OperationDataDefinition> operations = new HashMap<>();
+ final OperationDataDefinition operationDataDefinition = new OperationDataDefinition();
+ operationDataDefinition.setUniqueId(UUID.randomUUID().toString());
+ final ArtifactDataDefinition artifactDataDefinition = new ArtifactDataDefinition();
+
+ artifactDataDefinition.setArtifactName("EO Implementation info");
+ artifactDataDefinition.setArtifactType(artifactType);
+ PropertyDataDefinition propertyDataDefinition = new PropertyDataDefinition();
+ propertyDataDefinition.setName("input_range");
+ propertyDataDefinition.setType(inputType);
+ propertyDataDefinition.setValue("{\"input_range\": \"value2\"}");
+ artifactDataDefinition.addProperty(propertyDataDefinition);
+
+ operationDataDefinition.setImplementation(artifactDataDefinition);
+ operations.put("configure", operationDataDefinition);
+ interfaceDefinition.setOperations(operations );
+
+ DataTypeDefinition myType = new DataTypeDefinition();
+ final ArtifactTypeDefinition artifactTypeDefinitionFromCache = new ArtifactTypeDefinition();
+ artifactTypeDefinitionFromCache.setName(UniqueIdBuilder.buildArtifactTypeUid(null, artifactType));
+ myType.setName(inputType);
+ PropertyDefinition input_range = new PropertyDefinition();
+ input_range.setName("input_range");
+ input_range.setType("string");
+ PropertyConstraint constraint1 = new ValidValuesConstraint(Arrays.asList("value1", "value2", "value3"));
+ input_range.setConstraints(List.of(constraint1));
+ artifactTypeDefinitionFromCache.setProperties(List.of(input_range));
+ myType.setProperties(List.of(input_range));
+ Map<String, DataTypeDefinition> dataTypes = Collections.singletonMap(myType.getName(), myType);
+ Wrapper<ResponseFormat> errorWrapper = new Wrapper<>();
+
+ final ComponentInstanceInterface componentInstanceInterface =
+ new ComponentInstanceInterface("interfaceId", interfaceDefinition);
+ Map<String, List<ComponentInstanceInterface>> componentInstancesInterfacesMap = new HashMap<>();
+ componentInstancesInterfacesMap.put(componentInstanceId, Collections.singletonList(componentInstanceInterface));
+ component.setComponentInstancesInterfaces(componentInstancesInterfacesMap);
+ componentInstance.setInterfaces(
+ (Map<String, Object>) new HashMap<>().put(componentInstanceId, interfaceDefinition));
+ component.setComponentInstances(Collections.singletonList(componentInstance));
+
+ when(toscaOperationFacade.getToscaElement(componentId)).thenReturn(Either.left(component));
+ when(componentValidations.getComponentInstance(component, componentInstanceId))
+ .thenReturn(Optional.of(componentInstance));
+ when(toscaOperationFacade.updateComponentInstanceInterfaces(component, componentInstanceId))
+ .thenReturn(StorageOperationStatus.OK);
+ when(toscaOperationFacade
+ .updateComponentInstanceMetadataOfTopologyTemplate(any(Service.class), any(ComponentParametersView.class)))
+ .thenReturn(Either.left(component));
+ when(applicationDataTypeCache.getAll(null)).thenReturn(Either.left(dataTypes));
+ when(artifactTypeBusinessLogic.getArtifactTypeByUid(UniqueIdBuilder.buildArtifactTypeUid(
+ null, artifactType))).thenReturn(artifactTypeDefinitionFromCache);
+
+ final Optional<ComponentInstance> result = componentInterfaceOperationBusinessLogic
+ .updateComponentInstanceInterfaceOperation(componentId, componentInstanceId, interfaceDefinition,
+ ComponentTypeEnum.SERVICE, errorWrapper, false);
+ assertThat(result).isPresent();
+ }
+
+ private void initComponentData() {
try {
component = new Service();
component.setName("MyTestService");