From 82ee153edbf6ffca0d69bd450b48037ee0465191 Mon Sep 17 00:00:00 2001 From: vasraz Date: Thu, 15 Apr 2021 10:03:58 +0100 Subject: Fix 'Unable to save changed attributes default value' Implements missing functionality to save changed attribute Change-Id: I1bc828ef133c8a2bf2fd6333a51fb46fc41b6547 Signed-off-by: Vasyl Razinkov Issue-ID: SDC-3562 --- .../impl/ComponentInstanceBusinessLogic.java | 199 +++++++++++++++++++-- .../sdc/be/servlets/ComponentInstanceServlet.java | 99 +++++----- .../model/operations/impl/AttributeOperation.java | 33 ++++ .../attributes-outputs.page.component.ts | 60 ++++--- 4 files changed, 317 insertions(+), 74 deletions(-) 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 d0c72e566c..b602072354 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 @@ -79,6 +79,7 @@ import org.openecomp.sdc.be.impl.ForwardingPathUtils; import org.openecomp.sdc.be.impl.ServiceFilterUtils; import org.openecomp.sdc.be.info.CreateAndAssotiateInfo; import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.AttributeDefinition; import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; @@ -997,7 +998,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { throw new ByActionStatusComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, componentInstance.getName(), instanceType.getValue().toLowerCase()); } - if (!validateParentStatus.left().value()) { + if (!Boolean.TRUE.equals(validateParentStatus.left().value())) { throw new ByActionStatusComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, componentInstance.getName(), instanceType.getValue().toLowerCase(), containerComponentType.getValue().toLowerCase(), containerComponentId); } @@ -1062,7 +1063,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { ComponentInstance updatedCi = op.get(); updatedCi = buildComponentInstance(updatedCi, origInst); Boolean isUniqueName = validateInstanceNameUniquenessUponUpdate(containerComponent, origInst, updatedCi.getName()); - if (!isUniqueName) { + if (!Boolean.TRUE.equals(isUniqueName)) { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the name of the component instance {} to {}. A component instance with the same name already exists. ", origInst.getName(), updatedCi.getName()); @@ -1137,7 +1138,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { isNameChanged = true; } Boolean isUniqueName = validateInstanceNameUniquenessUponUpdate(containerComponent, oldComponentInstance, newInstanceName); - if (!isUniqueName) { + if (!Boolean.TRUE.equals(isUniqueName)) { CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update the name of the component instance {} to {}. A component instance with the same name already exists. ", oldComponentInstance.getName(), newInstanceName); @@ -1911,7 +1912,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Component containerComponent = getResourceResult.left().value(); if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) { - if (containerComponent.isArchived()) { + if (Boolean.TRUE.equals(containerComponent.isArchived())) { log.info("Component is archived. Component id: {}", componentId); return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, containerComponent.getName())); } @@ -1986,6 +1987,96 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } } + public Either, ResponseFormat> createOrUpdateAttributeValues(final ComponentTypeEnum componentTypeEnum, + final String componentId, + final String resourceInstanceId, + final List attributes, + final String userId) { + Either, ResponseFormat> resultOp = null; + /*-------------------------------Validations---------------------------------*/ + validateUserExists(userId); + + if (componentTypeEnum == null) { + BeEcompErrorManager.getInstance().logInvalidInputError("CreateOrUpdatePropertiesValues", INVALID_COMPONENT_TYPE, ErrorSeverity.INFO); + resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.NOT_ALLOWED)); + return resultOp; + } + final Either getResourceResult = toscaOperationFacade + .getToscaElement(componentId, JsonParseFlagEnum.ParseAll); + + if (getResourceResult.isRight()) { + log.debug(FAILED_TO_RETRIEVE_COMPONENT_COMPONENT_ID, componentId); + final ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getResourceResult.right().value(), componentTypeEnum); + return Either.right(componentsUtils.getResponseFormat(actionStatus, componentId)); + } + final Component containerComponent = getResourceResult.left().value(); + + if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) { + if (Boolean.TRUE.equals(containerComponent.isArchived())) { + log.info("Component is archived. Component id: {}", componentId); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, containerComponent.getName())); + } + log.info("Restricted operation for user: {} on service {}", userId, componentId); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); + } + + final Either resourceInstanceStatus = getResourceInstanceById(containerComponent, + resourceInstanceId); + if (resourceInstanceStatus.isRight()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, + resourceInstanceId, "resource instance", "service", componentId)); + } + final ComponentInstance foundResourceInstance = resourceInstanceStatus.left().value(); + + // lock resource + final StorageOperationStatus lockStatus = graphLockOperation.lockComponent(componentId, componentTypeEnum.getNodeType()); + if (lockStatus != StorageOperationStatus.OK) { + log.debug(FAILED_TO_LOCK_SERVICE, componentId); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockStatus))); + } + final List updatedProperties = new ArrayList<>(); + try { + for (final ComponentInstanceAttribute attribute : attributes) { + final ComponentInstanceAttribute componentInstanceProperty = validateAttributeExistsOnComponent(attribute, containerComponent, + foundResourceInstance); + final Either updatedPropertyValue = updateAttributeObjectValue(attribute); + if (updatedPropertyValue.isRight()) { + log.error("Failed to update attribute object value of attribute: {}", attribute); + throw new ByResponseFormatComponentException(updatedPropertyValue.right().value()); + } + updatedPropertyValue.bimap( + updatedValue -> { + componentInstanceProperty.setValue(updatedValue); + return updateAttributeOnContainerComponent(attribute, updatedValue, + containerComponent, foundResourceInstance); + }, Either::right); + updatedProperties.add(componentInstanceProperty); + } + + final Either updateContainerRes = toscaOperationFacade + .updateComponentInstanceMetadataOfTopologyTemplate(containerComponent); + if (updateContainerRes.isRight()) { + final ActionStatus actionStatus = componentsUtils + .convertFromStorageResponseForResourceInstanceProperty(updateContainerRes.right().value()); + resultOp = Either.right(componentsUtils.getResponseFormatForResourceInstanceProperty(actionStatus, "")); + return resultOp; + } + resultOp = Either.left(updatedProperties); + return resultOp; + + } catch (final ComponentException e) { + return Either.right(e.getResponseFormat()); + } finally { + if (resultOp == null || resultOp.isRight()) { + janusGraphDao.rollback(); + } else { + janusGraphDao.commit(); + } + // unlock resource + graphLockOperation.unlockComponent(componentId, componentTypeEnum.getNodeType()); + } + } + private void validateMandatoryFields(PropertyDataDefinition property) { if (StringUtils.isEmpty(property.getName())) { throw new ByActionStatusComponentException(ActionStatus.MISSING_PROPERTY_NAME); @@ -2004,6 +2095,19 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return instanceProperty.get(); } + private ComponentInstanceAttribute validateAttributeExistsOnComponent(final ComponentInstanceAttribute attribute, + final Component containerComponent, + final ComponentInstance foundResourceInstance) { + final List instanceProperties = + containerComponent.getComponentInstancesAttributes().get(foundResourceInstance.getUniqueId()); + final Optional instanceAttribute = + instanceProperties.stream().filter(p -> p.getName().equals(attribute.getName())).findAny(); + if (!instanceAttribute.isPresent()) { + throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND, attribute.getName()); + } + return instanceAttribute.get(); + } + private ResponseFormat updateCapabilityPropertyOnContainerComponent(ComponentInstanceProperty property, String newValue, Component containerComponent, ComponentInstance foundResourceInstance, @@ -2092,6 +2196,22 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return componentsUtils.getResponseFormat(ActionStatus.OK); } + private ResponseFormat updateAttributeOnContainerComponent(final ComponentInstanceAttribute instanceAttribute, + final String newValue, + final Component containerComponent, + final ComponentInstance foundResourceInstance) { + + instanceAttribute.setValue(newValue); + final StorageOperationStatus status = + toscaOperationFacade.updateComponentInstanceAttribute(containerComponent, foundResourceInstance.getUniqueId(), instanceAttribute); + if (status != StorageOperationStatus.OK) { + final ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForResourceInstanceProperty(status); + return componentsUtils.getResponseFormatForResourceInstanceProperty(actionStatus, ""); + } + foundResourceInstance.setCustomizationUUID(UUID.randomUUID().toString()); + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + private Either validatePropertyObjectValue(T property, String newValue, boolean isInput) { Either, JanusGraphOperationStatus> allDataTypesEither = dataTypeCache.getAll(); if (allDataTypesEither.isRight()) { @@ -2110,8 +2230,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Either isValid = propertyOperation .validateAndUpdatePropertyValue(property.getType(), newValue, true, innerType, allDataTypes); if (isValid.isRight()) { - Boolean res = isValid.right().value(); - if (!res) { + if (!Boolean.TRUE.equals(isValid.right().value())) { log.error("Invalid value {} of property {} ", newValue, property.getName()); return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); } @@ -2184,8 +2303,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Either isValid = propertyOperation .validateAndUpdatePropertyValue(propertyType, property.getValue(), true, innerType, allDataTypes); if (isValid.isRight()) { - Boolean res = isValid.right().value(); - if (!res) { + if (!Boolean.TRUE.equals(isValid.right().value())) { log.debug("validate and update property value has failed with value: {}", property.getValue()); throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse( DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT))); @@ -2199,7 +2317,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { if (!isInput) { ImmutablePair pair = propertyOperation .validateAndUpdateRules(propertyType, ((ComponentInstanceProperty) property).getRules(), innerType, allDataTypes, true); - if (pair.getRight() != null && pair.getRight() == false) { + 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)))); @@ -2208,6 +2326,58 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return Either.left(newValue); } + private Either updateAttributeObjectValue(final T attribute) { + final Either, JanusGraphOperationStatus> allDataTypesEither = dataTypeCache.getAll(); + if (allDataTypesEither.isRight()) { + JanusGraphOperationStatus status = allDataTypesEither.right().value(); + BeEcompErrorManager.getInstance() + .logInternalFlowError("UpdatePropertyValueOnComponentInstance", "Failed to update attribute value on instance. Status is " + status, + ErrorSeverity.ERROR); + return Either.right(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status)))); + } + String innerType = null; + final String attributeType = attribute.getType(); + final ToscaPropertyType type = ToscaPropertyType.isValidType(attributeType); + log.debug("The type of the attribute {} is {}", attribute.getUniqueId(), attributeType); + + if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) { + final SchemaDefinition def = attribute.getSchema(); + if (def == null) { + log.debug("Schema doesn't exists for attribute of type {}", type); + return Either + .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE))); + } + PropertyDataDefinition propDef = def.getProperty(); + if (propDef == null) { + log.debug("Property in Schema Definition inside attribute of type {} doesn't exist", type); + return Either + .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE))); + } + innerType = propDef.getType(); + } + + // Specific Update Logic + String newValue = attribute.getValue(); + + final Either isValid = attributeOperation + .validateAndUpdateAttributeValue(attributeType, attribute.getValue(), true, innerType, allDataTypesEither.left().value()); + if (isValid.isRight()) { + final Boolean res = isValid.right().value(); + if (!Boolean.TRUE.equals(res)) { + log.debug("validate and update attribute value has failed with value: {}", attribute.getValue()); + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse( + DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT))); + } + } else { + final Object object = isValid.left().value(); + if (object != null) { + newValue = object.toString(); + } + } + return Either.left(newValue); + } + private void validateToscaGetFunction(T property) { if (property.getToscaGetFunctionType() == ToscaGetFunctionType.GET_INPUT) { final List getInputValues = property.getGetInputValues(); @@ -2270,7 +2440,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Component containerComponent = getResourceResult.left().value(); if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) { - if (containerComponent.isArchived()) { + if (Boolean.TRUE.equals(containerComponent.isArchived())) { log.info("Component is archived. Component id: {}", componentId); return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, containerComponent.getName())); } @@ -2513,7 +2683,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { ActionStatus actionStatus = ActionStatus.CONTAINER_CANNOT_CONTAIN_COMPONENT_IN_STATE; throw new ByActionStatusComponentException(actionStatus, containerComponent.getComponentType().toString(), resourceCurrState.toString()); } - if (component.isArchived() == true) { + if (Boolean.TRUE.equals(component.isArchived())) { ActionStatus actionStatus = ActionStatus.COMPONENT_IS_ARCHIVED; throw new ByActionStatusComponentException(actionStatus, component.getName()); } @@ -2553,7 +2723,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { resultOp = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse (componentExistsRes.right().value()), resourceId)); return resultOp; - } else if (!componentExistsRes.left().value()) { + } else if (!Boolean.TRUE.equals(componentExistsRes.left().value())) { log.debug("The resource {} not found ", resourceId); resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId)); return resultOp; @@ -2636,7 +2806,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { log.debug("Failed to validate existing of the component {}. Status is {} ", resourceId, errorStatus); throw new ByActionStatusComponentException( componentsUtils.convertFromStorageResponse(errorStatus), resourceId); - } else if (!componentExistsRes.left().value()) { + } else if (!Boolean.TRUE.equals(componentExistsRes.left().value())) { log.debug("The resource {} not found ", resourceId); throw new ByActionStatusComponentException(ActionStatus.RESOURCE_NOT_FOUND, resourceId); } @@ -3325,7 +3495,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Either resultOp = null; validateUserExists(userId); if (componentTypeEnum == null) { - BeEcompErrorManager.getInstance().logInvalidInputError("createOrUpdateAttributeValue", INVALID_COMPONENT_TYPE, ErrorSeverity.INFO); + BeEcompErrorManager.getInstance() + .logInvalidInputError("createOrUpdateAttributeValueForCopyPaste", INVALID_COMPONENT_TYPE, ErrorSeverity.INFO); resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.NOT_ALLOWED)); return resultOp; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java index 551540023b..7816d3d0be 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java @@ -35,7 +35,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.tags.Tags; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; @@ -111,7 +110,7 @@ import org.springframework.stereotype.Controller; */ @Loggable(prepend = true, value = Loggable.DEBUG, trim = false) @Path("/v1/catalog") -@Tags({@Tag(name = "SDCE-2 APIs")}) +@Tag(name = "SDCE-2 APIs") @Server(url = "/sdc2/rest") @Controller public class ComponentInstanceServlet extends AbstractValidationsServlet { @@ -121,6 +120,7 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet { private static final String GET_GROUP_ARTIFACT_BY_ID_UNEXPECTED_EXCEPTION = "getGroupArtifactById unexpected exception"; private static final String GET_START_HANDLE_REQUEST_OF = "(GET) Start handle request of {}"; private static final String START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_PROPERTY_RECEIVED_PROPERTY_IS = "Start handle request of updateResourceInstanceProperty. Received property is {}"; + private static final String START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_ATTRIBUTE_RECEIVED_ATTRIBUTE_IS = "Start handle request of updateResourceInstanceAttribute. Received attribute is {}"; private static final String UPDATE_RESOURCE_INSTANCE = "Update Resource Instance"; private static final String RESOURCE_INSTANCE_UPDATE_RESOURCE_INSTANCE = "Resource Instance - updateResourceInstance"; private static final String UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION = "update resource instance with exception"; @@ -641,10 +641,10 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet { * @return */ @POST - @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/attribute") + @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/attributes") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - @Operation(description = "Update resource instance attribute", method = "POST", summary = "Returns updated resource instance attribute", responses = { + @Operation(description = "Update resource instance attribute", method = "POST", summary = "Returns updated resource instance property", responses = { @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))), @ApiResponse(responseCode = "201", description = "Resource instance created"), @ApiResponse(responseCode = "403", description = "Restricted operation"), @@ -655,45 +655,52 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet { ComponentTypeEnum.RESOURCE_PARAM_NAME, ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType, @Parameter(description = "resource instance id") @PathParam("componentInstanceId") final String componentInstanceId, - @Parameter(description = "id of user initiating the operation") @HeaderParam(value = Constants.USER_ID_HEADER) String userId, - @Context final HttpServletRequest request) throws IOException { - String url = request.getMethod() + " " + request.getRequestURI(); + @Parameter(description = "id of user initiating the operation") @HeaderParam(value = Constants.USER_ID_HEADER) final String userId, + @Context final HttpServletRequest request, + @Parameter(description = "Component Instance Properties JSON Array", required = true) final String componentInstanceAttributesJsonArray) { + final String url = request.getMethod() + " " + request.getRequestURI(); log.debug(START_HANDLE_REQUEST_OF, url); - loggerSupportability - .log(LoggerSupportabilityActions.UPDATE_RESOURCE, StatusCode.STARTED, "Starting to update Resource Instance Attribute for component {} ", - componentId + " by " + userId); - try { - Wrapper errorWrapper = new Wrapper<>(); - Wrapper dataWrapper = new Wrapper<>(); - Wrapper attributeWrapper = new Wrapper<>(); - Wrapper blWrapper = new Wrapper<>(); - validateInputStream(request, dataWrapper, errorWrapper); - if (errorWrapper.isEmpty()) { - validateClassParse(dataWrapper.getInnerElement(), attributeWrapper, () -> ComponentInstanceProperty.class, errorWrapper); - } - if (errorWrapper.isEmpty()) { - validateComponentInstanceBusinessLogic(request, containerComponentType, blWrapper, errorWrapper); - } - if (errorWrapper.isEmpty()) { - ComponentInstanceBusinessLogic componentInstanceLogic = blWrapper.getInnerElement(); - ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType); - log.debug("Start handle request of ComponentInstanceAttribute. Received attribute is {}", attributeWrapper.getInnerElement()); - Either eitherAttribute = componentInstanceLogic - .createOrUpdateAttributeValue(componentTypeEnum, componentId, componentInstanceId, attributeWrapper.getInnerElement(), userId); - if (eitherAttribute.isRight()) { - errorWrapper.setInnerElement(eitherAttribute.right().value()); - } else { - attributeWrapper.setInnerElement(eitherAttribute.left().value()); - } + loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.STARTED, + "Starting to update Resource Instance Attributes for component {} ", componentId + " by " + userId); + final Wrapper errorWrapper = new Wrapper<>(); + List attributesToUpdate = new ArrayList<>(); + if (errorWrapper.isEmpty()) { + final Either, ResponseFormat> attributesToUpdateEither = convertMultipleAttributes( + componentInstanceAttributesJsonArray); + if (attributesToUpdateEither.isRight()) { + errorWrapper.setInnerElement(attributesToUpdateEither.right().value()); + } else { + attributesToUpdate = attributesToUpdateEither.left().value(); } - loggerSupportability - .log(LoggerSupportabilityActions.UPDATE_RESOURCE, StatusCode.COMPLETE, "Ended update Resource Instance Attribute for component {} ", - componentId + " by " + userId); - return buildResponseFromElement(errorWrapper, attributeWrapper); - } catch (Exception e) { - log.error(CREATE_AND_ASSOCIATE_RI_FAILED_WITH_EXCEPTION, e.getMessage(), e); - throw e; } + if (!errorWrapper.isEmpty()) { + return buildErrorResponse(errorWrapper.getInnerElement()); + } + log.debug(START_HANDLE_REQUEST_OF_UPDATE_RESOURCE_INSTANCE_ATTRIBUTE_RECEIVED_ATTRIBUTE_IS, attributesToUpdate); + final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType); + if (componentInstanceBusinessLogic == null) { + log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType)); + } + final Either, ResponseFormat> actionResponse = componentInstanceBusinessLogic + .createOrUpdateAttributeValues(componentTypeEnum, componentId, componentInstanceId, attributesToUpdate, userId); + if (actionResponse.isRight()) { + return buildErrorResponse(actionResponse.right().value()); + } + final List resourceInstanceAttributes = actionResponse.left().value(); + final ObjectMapper mapper = new ObjectMapper(); + String result; + loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.COMPLETE, + "Ended update Resource Instance Attributes for component {} ", componentId + " by " + userId); + try { + result = mapper.writeValueAsString(resourceInstanceAttributes); + } catch (JsonProcessingException e) { + log.error(UPDATE_RESOURCE_INSTANCE_WITH_EXCEPTION, e.getMessage(), e); + throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); + } + loggerSupportability.log(LoggerSupportabilityActions.UPDATE_COMPONENT_INSTANCE, StatusCode.COMPLETE, + "Ended update Resource Instance Attributes for component {} ", componentId + " by user " + userId); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result); } @DELETE @@ -1258,6 +1265,18 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet { return Either.left(Arrays.asList(convertStatus.left().value())); } + private Either, ResponseFormat> convertMultipleAttributes(final String dataList) { + if (StringUtils.isEmpty(dataList)) { + return Either.right(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_BODY)); + } + final Either convertStatus = getComponentsUtils(). + convertJsonToObjectUsingObjectMapper(dataList, new User(), ComponentInstanceAttribute[].class, null, ComponentTypeEnum.RESOURCE_INSTANCE); + if (convertStatus.isRight()) { + return Either.right(convertStatus.right().value()); + } + return Either.left(Arrays.asList(convertStatus.left().value())); + } + private Either, ResponseFormat> convertMultipleInputs(String dataList) { if (StringUtils.isEmpty(dataList)) { return Either.right(getComponentsUtils().getResponseFormat(ActionStatus.MISSING_BODY)); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/AttributeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/AttributeOperation.java index 0adb90de80..f2e8c83b26 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/AttributeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/AttributeOperation.java @@ -315,4 +315,37 @@ public class AttributeOperation extends AbstractOperation { private void updateAttributeValue(final AttributeDataDefinition attributeDefinition, final JsonElement jsonElement) { attributeDefinition.set_default(jsonElement); } + + public Either validateAndUpdateAttributeValue(final String attributeType, + final String value, + final boolean isValidate, + final String innerType, + final Map dataTypes) { + log.trace("Going to validate attribute value and its type. type = {}, value = {}", attributeType, value); + final ToscaPropertyType type = getType(attributeType); + if (isValidate) { + if (type == null) { + final DataTypeDefinition dataTypeDefinition = dataTypes.get(attributeType); + final ImmutablePair validateResult = + dataTypeValidatorConverter.validateAndUpdate(value, dataTypeDefinition, dataTypes); + if (Boolean.FALSE.equals(validateResult.right)) { + log.debug(THE_VALUE_OF_ATTRIBUTE_FROM_TYPE_IS_INVALID, value, attributeType); + return Either.right(false); + } + return Either.left(getValueFromJsonElement(validateResult.left)); + } + log.trace("before validating property type {}", attributeType); + if (!isValidValue(type, value, innerType, dataTypes)) { + log.debug(THE_VALUE_OF_ATTRIBUTE_FROM_TYPE_IS_INVALID, value, type); + return Either.right(false); + } + } + Object convertedValue = value; + if (!isEmptyValue(value) && isValidate) { + PropertyValueConverter converter = type.getConverter(); + convertedValue = converter.convert(value, innerType, dataTypes); + } + return Either.left(convertedValue); + } + } diff --git a/catalog-ui/src/app/ng2/pages/attributes-outputs/attributes-outputs.page.component.ts b/catalog-ui/src/app/ng2/pages/attributes-outputs/attributes-outputs.page.component.ts index d7db8f3c82..f97f8499ea 100644 --- a/catalog-ui/src/app/ng2/pages/attributes-outputs/attributes-outputs.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/attributes-outputs/attributes-outputs.page.component.ts @@ -198,7 +198,6 @@ export class AttributesOutputsComponent { event.preventDefault(); this.showUnsavedChangesAlert().then(() => { this.$state.go(toState, toParams); - }, () => { }); } }); @@ -390,7 +389,6 @@ export class AttributesOutputsComponent { this.attributeOutputTabs.triggerTabChange(this.currentMainTab.title); this.showUnsavedChangesAlert().then(() => { this.attributeOutputTabs.selectTab(this.attributeOutputTabs.tabs.find((tab) => tab.title === event.title)); - }, () => { }); return; } @@ -451,7 +449,7 @@ export class AttributesOutputsComponent { let request; let handleSuccess, handleError; if (this.isAttributesTabSelected) { - this.changedData.map((changedAttrib) => { + const changedAttribs = this.changedData.map((changedAttrib) => { changedAttrib = changedAttrib; const attribBE = new AttributeBEModel(changedAttrib); attribBE.toscaPresentation = new ToscaPresentationData(); @@ -461,6 +459,28 @@ export class AttributesOutputsComponent { delete attribBE.origName; return attribBE; }); + + if (this.selectedInstanceData instanceof ComponentInstance) { + if (this.isSelf()) { + console.log("changedAttribs", changedAttribs); + request = this.topologyTemplateService.updateServiceAttributes(this.component.uniqueId, _.map(changedAttribs, cp => { + delete cp.constraints; + return cp; + })); + } else { + request = this.componentInstanceServiceNg2 + .updateInstanceAttributes(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedAttribs); + } + handleSuccess = (response) => { + // reset each changed attribute with new value and remove it from changed attributes list + response.forEach((resAttrib) => { + const changedAttrib = this.changedData.shift(); + this.attributesUtils.resetAttributeValue(changedAttrib, resAttrib.value); + }); + resolve(response); + console.log("updated instance attributes: ", response); + }; + } } else if (this.isOutputsTabSelected) { const changedOutputs: OutputBEModel[] = this.changedData.map((changedOutput) => { changedOutput = changedOutput; @@ -468,8 +488,7 @@ export class AttributesOutputsComponent { outputBE.defaultValue = changedOutput.getJSONDefaultValue(); return outputBE; }); - request = this.componentServiceNg2 - .updateComponentOutputs(this.component, changedOutputs); + request = this.componentServiceNg2.updateComponentOutputs(this.component, changedOutputs); handleSuccess = (response) => { // reset each changed attribute with new value and remove it from changed attributes list response.forEach((resOutput) => { @@ -478,23 +497,24 @@ export class AttributesOutputsComponent { changedOutput.required = resOutput.required; }); } - this.savingChangedData = true; - request.subscribe( - (response) => { - this.savingChangedData = false; - handleSuccess && handleSuccess(response); - this.updateHasChangedData(); - resolve(response); - }, - (error) => { - this.savingChangedData = false; - handleError && handleError(error); - this.updateHasChangedData(); - reject(error); - } - ); } + this.savingChangedData = true; + request.subscribe( + (response) => { + this.savingChangedData = false; + handleSuccess && handleSuccess(response); + this.updateHasChangedData(); + resolve(response); + }, + (error) => { + this.savingChangedData = false; + handleError && handleError(error); + this.updateHasChangedData(); + reject(error); + } + ); + }); }; -- cgit 1.2.3-korg