From 6cffd9e3eecb10281d880ea7d217f0ecddf8fb5a Mon Sep 17 00:00:00 2001 From: vasraz Date: Thu, 31 Mar 2022 13:35:04 +0100 Subject: Update Interface definition on VFC Signed-off-by: aribeiro Change-Id: I13678c92ae6088016a78554ffaf0da47b82f7e65 Signed-off-by: Vasyl Razinkov Issue-ID: SDC-3893 Signed-off-by: andre.schmid --- .../ComponentInterfaceOperationBusinessLogic.java | 73 +++++++++++++++++++++- .../impl/InterfaceDefinitionHandler.java | 2 +- .../impl/InterfaceOperationBusinessLogic.java | 57 +++++++++-------- .../be/components/impl/ResourceImportManager.java | 5 +- .../ComponentInterfaceOperationServlet.java | 61 ++++++++++++++++-- .../be/tosca/builder/ToscaRelationshipBuilder.java | 2 +- .../be/components/ResourceImportManagerTest.java | 4 +- 7 files changed, 163 insertions(+), 41 deletions(-) (limited to 'catalog-be') diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogic.java index 9eaf1eec3d..57571c0b49 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogic.java @@ -108,8 +108,8 @@ public class ComponentInterfaceOperationBusinessLogic extends BaseBusinessLogic } final OperationDataDefinition updatedOperationDataDefinition = optionalOperationDataDefinition.get(); final Optional optionalComponentInstanceInterface = componentInstanceInterfaceList.stream().filter( - ci -> ci.getOperations().values().stream().anyMatch( - operationDataDefinition -> operationDataDefinition.getUniqueId().equalsIgnoreCase(updatedOperationDataDefinition.getUniqueId()))) + ci -> ci.getOperations().values().stream().anyMatch( + operationDataDefinition -> operationDataDefinition.getUniqueId().equalsIgnoreCase(updatedOperationDataDefinition.getUniqueId()))) .findFirst(); if (optionalComponentInstanceInterface.isEmpty()) { responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT); @@ -164,6 +164,75 @@ public class ComponentInterfaceOperationBusinessLogic extends BaseBusinessLogic return componentInstanceOptional; } + public Optional updateResourceInterfaceOperation(final String componentId, + final InterfaceDefinition interfaceDefinition, + final ComponentTypeEnum componentTypeEnum, + final Wrapper errorWrapper, + final boolean shouldLock) throws BusinessLogicException { + final var component = getComponent(componentId); + ResponseFormat responseFormat; + + Map componentInterfaceMap = component.getInterfaces(); + final String interfaceDefinitionType = interfaceDefinition.getType(); + if (MapUtils.isEmpty(componentInterfaceMap)) { + componentInterfaceMap = new HashMap<>(); + componentInterfaceMap.put(interfaceDefinitionType, interfaceDefinition); + component.setInterfaces(componentInterfaceMap); + } else { + InterfaceDefinition componentInterfaceDefinition = componentInterfaceMap.get(interfaceDefinitionType); + if (componentInterfaceDefinition == null) { + componentInterfaceDefinition = interfaceDefinition; + componentInterfaceMap.put(interfaceDefinitionType, interfaceDefinition); + } + + final Map interfaceDefinitionOperations = interfaceDefinition.getOperations(); + final Optional optionalOperationDataDefinition = interfaceDefinitionOperations.values().stream().findFirst(); + if (optionalOperationDataDefinition.isEmpty()) { + responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND); + LOGGER.debug("Failed to found interface operation on provided InterfaceDefinition {}, error: {}", + interfaceDefinitionType, responseFormat); + errorWrapper.setInnerElement(responseFormat); + return Optional.empty(); + } + final var updatedOperationDataDefinition = optionalOperationDataDefinition.get(); + updateOperationDefinitionImplementation(updatedOperationDataDefinition); + Map componentOperationDataDefinitionMap = componentInterfaceDefinition.getOperations(); + if (MapUtils.isEmpty(componentOperationDataDefinitionMap)) { + componentOperationDataDefinitionMap = new HashMap<>(); + componentInterfaceDefinition.setOperations(componentOperationDataDefinitionMap); + } + componentOperationDataDefinitionMap.replace(updatedOperationDataDefinition.getName(), updatedOperationDataDefinition); + } + boolean wasLocked = false; + try { + if (shouldLock) { + lockComponent(componentId, component, "Update Interface Operation on Component instance"); + wasLocked = true; + } + final StorageOperationStatus status = + toscaOperationFacade.updateComponentInterfaces(component.getUniqueId(), component.getInterfaces(), interfaceDefinitionType); + if (status != StorageOperationStatus.OK) { + janusGraphDao.rollback(); + responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + LOGGER.error("Exception occurred when updating Component Instance Interfaces {}", responseFormat); + errorWrapper.setInnerElement(responseFormat); + return Optional.empty(); + } + janusGraphDao.commit(); + } catch (final Exception e) { + janusGraphDao.rollback(); + LOGGER.error("Exception occurred when updating Interface Operation on Component Instance: ", e); + responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + errorWrapper.setInnerElement(responseFormat); + throw new BusinessLogicException(responseFormat); + } finally { + if (wasLocked) { + unlockComponent(component.getUniqueId(), componentTypeEnum); + } + } + return Optional.of(component); + } + public User validateUser(final String userId) { final User user = userValidations.validateUserExists(userId); userValidations.validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN)); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceDefinitionHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceDefinitionHandler.java index af41007c95..9d9d864fa6 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceDefinitionHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceDefinitionHandler.java @@ -88,7 +88,7 @@ public class InterfaceDefinitionHandler { } final String type = (String) typeObj; interfaceDefinition.setType(type); - interfaceDefinition.setUniqueId(type.toLowerCase()); + interfaceDefinition.setUniqueId(type); } final Map inputDefinitionMap = handleInputs(interfaceDefinitionToscaMap); if (!inputDefinitionMap.isEmpty()) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java index d633141fdf..6b861a104e 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java @@ -40,6 +40,7 @@ import java.util.UUID; import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils; @@ -47,6 +48,7 @@ import org.openecomp.sdc.be.components.validation.InterfaceOperationValidation; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao; import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus; +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; @@ -290,39 +292,42 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic { } else { Optional> optionalOperation = getOperationFromInterfaceDefinition(interfaceDef, operation.getUniqueId()); - if (!optionalOperation.isPresent()) { + if (optionalOperation.isEmpty()) { janusGraphDao.rollback(); return Either .right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, storedComponent.getUniqueId())); } - Operation storedOperation = optionalOperation.get().getValue(); - String artifactUuId = storedOperation.getImplementation().getArtifactUUID(); - String artifactUniqueId = storedOperation.getImplementation().getUniqueId(); - if (!InterfaceOperationUtils.isArtifactInUse(storedComponent, storedOperation.getUniqueId(), artifactUniqueId)) { - Either getArtifactEither = artifactToscaOperation - .getArtifactById(storedComponent.getUniqueId(), artifactUniqueId); - if (getArtifactEither.isLeft()) { - Either removeArifactFromComponent = artifactToscaOperation - .removeArifactFromResource(componentId, artifactUniqueId, - NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()), true); - if (removeArifactFromComponent.isRight()) { - janusGraphDao.rollback(); - ResponseFormat responseFormatByArtifactId = componentsUtils.getResponseFormatByArtifactId( - componentsUtils.convertFromStorageResponse(removeArifactFromComponent.right().value()), - storedOperation.getImplementation().getArtifactDisplayName()); - return Either.right(responseFormatByArtifactId); - } - CassandraOperationStatus cassandraStatus = artifactCassandraDao.deleteArtifact(artifactUniqueId); - if (cassandraStatus != CassandraOperationStatus.OK) { - janusGraphDao.rollback(); - ResponseFormat responseFormatByArtifactId = componentsUtils.getResponseFormatByArtifactId( - componentsUtils.convertFromStorageResponse(componentsUtils.convertToStorageOperationStatus(cassandraStatus)), - storedOperation.getImplementation().getArtifactDisplayName()); - return Either.right(responseFormatByArtifactId); + final Operation storedOperation = optionalOperation.get().getValue(); + final ArtifactDataDefinition implementation = storedOperation.getImplementation(); + final String artifactUniqueId = implementation.getUniqueId(); + if (StringUtils.isNotEmpty(artifactUniqueId)) { + if (!InterfaceOperationUtils.isArtifactInUse(storedComponent, storedOperation.getUniqueId(), artifactUniqueId)) { + Either getArtifactEither = artifactToscaOperation + .getArtifactById(storedComponent.getUniqueId(), artifactUniqueId); + if (getArtifactEither.isLeft()) { + Either removeArifactFromComponent = artifactToscaOperation + .removeArifactFromResource(componentId, artifactUniqueId, + NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()), true); + if (removeArifactFromComponent.isRight()) { + janusGraphDao.rollback(); + ResponseFormat responseFormatByArtifactId = componentsUtils.getResponseFormatByArtifactId( + componentsUtils.convertFromStorageResponse(removeArifactFromComponent.right().value()), + implementation.getArtifactDisplayName()); + return Either.right(responseFormatByArtifactId); + } + CassandraOperationStatus cassandraStatus = artifactCassandraDao.deleteArtifact(artifactUniqueId); + if (cassandraStatus != CassandraOperationStatus.OK) { + janusGraphDao.rollback(); + ResponseFormat responseFormatByArtifactId = componentsUtils.getResponseFormatByArtifactId( + componentsUtils.convertFromStorageResponse( + componentsUtils.convertToStorageOperationStatus(cassandraStatus)), + implementation.getArtifactDisplayName()); + return Either.right(responseFormatByArtifactId); + } } } } - updateOperationOnInterface(interfaceDef, operation, artifactUuId); + updateOperationOnInterface(interfaceDef, operation, implementation.getArtifactUUID()); } } interfacesCollection.add(interfaceDef); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java index cbae55d952..8c6e9cb2a2 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java @@ -392,15 +392,14 @@ public class ResourceImportManager { Either, ResultStatusEnum> toscaInterfaces = ImportUtils .findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.INTERFACES); if (toscaInterfaces.isLeft()) { - Map jsonInterfaces = toscaInterfaces.left().value(); Map moduleInterfaces = new HashMap<>(); - for (final Entry interfaceNameValue : jsonInterfaces.entrySet()) { + for (final Entry interfaceNameValue : toscaInterfaces.left().value().entrySet()) { final Either eitherInterface = createModuleInterface(interfaceNameValue.getValue(), resource.getModel()); if (eitherInterface.isRight()) { log.info("error when creating interface:{}, for resource:{}", interfaceNameValue.getKey(), resource.getName()); } else { final InterfaceDefinition interfaceDefinition = eitherInterface.left().value(); - moduleInterfaces.put(interfaceNameValue.getKey(), interfaceDefinition); + moduleInterfaces.put(interfaceDefinition.getType(), interfaceDefinition); } } if (!moduleInterfaces.isEmpty()) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInterfaceOperationServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInterfaceOperationServlet.java index cbf14da3fd..83ee15240f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInterfaceOperationServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInterfaceOperationServlet.java @@ -20,6 +20,8 @@ */ package org.openecomp.sdc.be.servlets; +import static org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum.RESOURCE; + import fj.data.Either; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -27,8 +29,8 @@ import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; 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.util.Optional; import javax.servlet.http.HttpServletRequest; @@ -52,6 +54,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.User; @@ -67,10 +70,11 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; -@Path("/v1/catalog/{componentType}/{componentId}/componentInstance/{componentInstanceId}/interfaceOperation") +@Path("/v1/catalog") @Tag(name = "SDCE-2 APIs") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) +@Server(url = "/sdc2/rest") @Controller public class ComponentInterfaceOperationServlet extends AbstractValidationsServlet { @@ -95,6 +99,7 @@ public class ComponentInterfaceOperationServlet extends AbstractValidationsServl } @PUT + @Path("/{componentType}/{componentId}/componentInstance/{componentInstanceId}/interfaceOperation") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Operation(description = "Update Interface Operation", method = "PUT", summary = "Update Interface Operation on ComponentInstance", responses = { @@ -136,15 +141,59 @@ public class ComponentInterfaceOperationServlet extends AbstractValidationsServl final Optional actionResponse = componentInterfaceOperationBusinessLogic .updateComponentInstanceInterfaceOperation(componentId, componentInstanceId, mappedInterfaceOperationData.get(), componentTypeEnum, errorWrapper, true); - final Response response; if (actionResponse.isEmpty()) { LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION, componentInstanceId); - response = buildErrorResponse(errorWrapper.getInnerElement()); + return buildErrorResponse(errorWrapper.getInnerElement()); } else { LOGGER.debug(INTERFACE_OPERATION_SUCCESSFULLY_UPDATED, componentInstanceId); - response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.get()); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.get()); + } + } catch (final Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError(UPDATE_INTERFACE_OPERATION); + LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION_WITH_ERROR, e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + @PUT + @Path("/resources/{componentId}/interfaceOperation") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Update Interface Operation", method = "PUT", summary = "Update Interface Operation on ComponentInstance", responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))), + @ApiResponse(responseCode = "201", description = "Update Interface Operation"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")}) + @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) + public Response updateResourceInterfaceOperation( + @Parameter(description = "Component Id") @PathParam("componentId") String componentId, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException { + LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI()); + LOGGER.debug(MODIFIER_ID_IS, userId); + final User userModifier = componentInterfaceOperationBusinessLogic.validateUser(userId); + final ComponentTypeEnum componentTypeEnum = RESOURCE; + final byte[] bytes = IOUtils.toByteArray(request.getInputStream()); + if (bytes == null || bytes.length == 0) { + LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + final String data = new String(bytes); + final Optional mappedInterfaceOperationData = getMappedInterfaceData(data, userModifier, componentTypeEnum); + if (mappedInterfaceOperationData.isEmpty()) { + LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID, data); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + final Wrapper errorWrapper = new Wrapper<>(); + try { + final Optional actionResponse = componentInterfaceOperationBusinessLogic + .updateResourceInterfaceOperation(componentId, mappedInterfaceOperationData.get(), componentTypeEnum, errorWrapper, true); + if (actionResponse.isEmpty()) { + LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION, componentId); + return buildErrorResponse(errorWrapper.getInnerElement()); + } else { + LOGGER.debug(INTERFACE_OPERATION_SUCCESSFULLY_UPDATED, componentId); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.get()); } - return response; } catch (final Exception e) { BeEcompErrorManager.getInstance().logBeRestApiGeneralError(UPDATE_INTERFACE_OPERATION); LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION_WITH_ERROR, e); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/builder/ToscaRelationshipBuilder.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/builder/ToscaRelationshipBuilder.java index 1dec236fff..cd0ea1922b 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/builder/ToscaRelationshipBuilder.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/builder/ToscaRelationshipBuilder.java @@ -60,7 +60,7 @@ public class ToscaRelationshipBuilder { operationDefinitionMap.put(operationUi.getOperationType(), toscaOperationAssignment); } toscaInterfaceDefinition.setOperations(operationDefinitionMap); - interfaceMap.put(InterfaceTypesNameUtil.buildShortName(interfaceType), toscaInterfaceDefinition); + interfaceMap.put(interfaceType, toscaInterfaceDefinition); } toscaRelationship.setInterfaces(interfaceMap); return toscaRelationship; diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java index 40c9b437c1..6f20e2d469 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java @@ -514,8 +514,8 @@ public class ResourceImportManagerTest { final Map interfaces = resource.getInterfaces(); assertNotNull(interfaces); assertEquals(1, interfaces.size()); - final InterfaceDefinition interfaceDefinition = interfaces.get("Standard"); - assertTrue(interfaces.containsKey(InterfaceTypesNameUtil.buildShortName(interfaceDefinition.getType()))); + final InterfaceDefinition interfaceDefinition = interfaces.get("tosca.interfaces.node.lifecycle.Standard"); + assertTrue(interfaces.containsKey(interfaceDefinition.getType())); Map operations = interfaceDefinition.getOperations(); operations.values().forEach(operationDataDefinition -> assertTrue(operations.containsKey(operationDataDefinition.getName()))); -- cgit 1.2.3-korg