From ceaf83e0f29c10e4521321abcd6dd17080d2db60 Mon Sep 17 00:00:00 2001 From: JvD_Ericsson Date: Mon, 11 Sep 2023 10:56:37 +0100 Subject: Support setting interfaces on instances Issue-ID: SDC-4620 Signed-off-by: JvD_Ericsson Change-Id: I4f78eb5e017e79120d61870ecc3b7268f83b4206 --- .../ComponentInterfaceOperationBusinessLogic.java | 79 ++++++++++++++++++++++ .../components/utils/InterfaceOperationUtils.java | 2 + .../ComponentInterfaceOperationServlet.java | 60 +++++++++++++++- 3 files changed, 140 insertions(+), 1 deletion(-) (limited to 'catalog-be/src/main') 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 3ac8ce3562..a10bae9c1e 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 @@ -37,6 +37,7 @@ import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.ListUtils; import org.apache.commons.collections.MapUtils; import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; import org.openecomp.sdc.be.components.validation.ComponentValidations; @@ -306,6 +307,84 @@ public class ComponentInterfaceOperationBusinessLogic extends BaseBusinessLogic return Optional.of(component); } + public Optional createComponentInstanceInterfaceOperation(String componentId, String componentInstanceId, + InterfaceDefinition interfaceDefinition, + ComponentTypeEnum componentTypeEnum, + Wrapper errorWrapper, final boolean shouldLock) + throws BusinessLogicException { + ResponseFormat responseFormat; + final Component component = getComponent(componentId); + final Optional componentInstanceOptional = componentValidations.getComponentInstance(component, componentInstanceId); + if (componentInstanceOptional.isEmpty()) { + responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND); + LOGGER.debug("Failed to find component instance with id {}, error: {}", componentInstanceId, responseFormat); + errorWrapper.setInnerElement(responseFormat); + return Optional.empty(); + } + Map> componentInstancesInterfaceMap = component.getComponentInstancesInterfaces(); + if (MapUtils.isEmpty(componentInstancesInterfaceMap)) { + componentInstancesInterfaceMap = new HashMap<>(); + component.setComponentInstancesInterfaces(componentInstancesInterfaceMap); + } + final String interfaceKey = interfaceDefinition.getType(); + interfaceDefinition.setUniqueId(interfaceKey); + interfaceDefinition.setToscaResourceName(interfaceKey); + interfaceDefinition.setUserCreated(true); + + final Optional optionalOperationDataDefinition = interfaceDefinition.getOperations().values().stream().findFirst(); + if (optionalOperationDataDefinition.isEmpty()) { + responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND, interfaceKey); + LOGGER.debug("Failed to find interface operation on interface being added {}, error: {}", interfaceKey, responseFormat); + errorWrapper.setInnerElement(responseFormat); + return Optional.empty(); + } + + final OperationDataDefinition updatedOperationDataDefinition = optionalOperationDataDefinition.get(); + updatedOperationDataDefinition.setUniqueId(UUID.randomUUID().toString()); + updatedOperationDataDefinition.getImplementation() + .setArtifactName(generateArtifactName(updatedOperationDataDefinition.getImplementation().getArtifactName())); + + List componentInstanceInterfaceList = componentInstancesInterfaceMap.get(componentInstanceId); + componentInstanceInterfaceList = CollectionUtils.isEmpty(componentInstanceInterfaceList) ? new ArrayList<>() : componentInstanceInterfaceList; + Optional componentInstanceInterface = + componentInstanceInterfaceList.stream().filter(instInterface -> instInterface.getInterfaceId().equals(interfaceKey)).findFirst(); + + if (componentInstanceInterface.isEmpty()) { + componentInstanceInterfaceList.add(new ComponentInstanceInterface(interfaceKey, interfaceDefinition)); + componentInstanceOptional.get().addInterface(interfaceKey, interfaceDefinition); + } else { + componentInstanceInterface.get().getOperations().put(updatedOperationDataDefinition.getName(), updatedOperationDataDefinition); + } + + boolean wasLocked = false; + try { + if (shouldLock) { + lockComponent(componentId, component, UPDATE_INTERFACE_OPERATION_ON_COMPONENT_INSTANCE); + wasLocked = true; + } + 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); + 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.getMessage(), e); + responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + errorWrapper.setInnerElement(responseFormat); + throw new BusinessLogicException(responseFormat); + } finally { + if (wasLocked) { + unlockComponent(component.getUniqueId(), componentTypeEnum); + } + } + return componentInstanceOptional; + } + public Optional createInterfaceOperationInResource(final String componentId, final InterfaceDefinition interfaceDefinition, final ComponentTypeEnum componentTypeEnum, final Wrapper errorWrapper, final boolean shouldLock) diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java index edbad79e14..ae94d9803d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.openecomp.sdc.be.components.utils; import java.util.ArrayList; @@ -31,6 +32,7 @@ import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition; import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstanceInterface; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.Operation; 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 fbb7d0b0ac..1e68b0f431 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 @@ -18,6 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ + package org.openecomp.sdc.be.servlets; import static org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum.RESOURCE; @@ -87,7 +88,8 @@ public class ComponentInterfaceOperationServlet extends AbstractValidationsServl private static final String FAILED_TO_UPDATE_INTERFACE_OPERATION_WITH_ERROR = "Failed to update Interface Operation with an error"; private static final String INTERFACE_OPERATION_CONTENT_INVALID = "Interface Operation content is invalid - {}"; private static final String UNSUPPORTED_COMPONENT_TYPE = "Unsupported component type {}"; - private static final String INTERFACE_OPERATION_SUCCESSFULLY_UPDATED = "Interface Operation successfully updated on component instance with id {}"; + private static final String INTERFACE_OPERATION_SUCCESSFULLY_UPDATED = + "Interface Operation successfully updated on component instance with id {}"; private final ComponentInterfaceOperationBusinessLogic componentInterfaceOperationBusinessLogic; @Autowired @@ -205,6 +207,62 @@ public class ComponentInterfaceOperationServlet extends AbstractValidationsServl } } + @POST + @Path("/{componentType}/{componentId}/componentInstance/{componentInstanceId}/interfaceOperation") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Create Interface Operation", method = "POST", summary = "Create Interface Operation on ComponentInstance", responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))), + @ApiResponse(responseCode = "201", description = "Create Interface Operation"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")}) + @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) + public Response createComponentInstanceInterfaceOperation( + @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME, + ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("componentType") String componentType, + @Parameter(description = "Component Id") @PathParam("componentId") String componentId, + @Parameter(description = "Component Instance Id") @PathParam("componentInstanceId") String componentInstanceId, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException { + LOGGER.debug(START_HANDLE_REQUEST_OF, request.getMethod(), request.getRequestURI()); + userId = ValidationUtils.sanitizeInputString(userId); + componentType = ValidationUtils.sanitizeInputString(componentType); + componentInstanceId = ValidationUtils.sanitizeInputString(componentInstanceId); + LOGGER.debug(MODIFIER_ID_IS, userId); + final User userModifier = componentInterfaceOperationBusinessLogic.validateUser(userId); + final ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType); + if (componentTypeEnum == null) { + LOGGER.debug(UNSUPPORTED_COMPONENT_TYPE, componentType); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, componentType)); + } + final byte[] bytes = IOUtils.toByteArray(request.getInputStream()); + if (bytes == null || bytes.length == 0) { + LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID, "content is empty"); + 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.createComponentInstanceInterfaceOperation( + componentId, componentInstanceId, mappedInterfaceOperationData.get(), componentTypeEnum, errorWrapper, true); + if (actionResponse.isEmpty()) { + LOGGER.error(FAILED_TO_UPDATE_INTERFACE_OPERATION, componentInstanceId); + return buildErrorResponse(errorWrapper.getInnerElement()); + } else { + LOGGER.debug(INTERFACE_OPERATION_SUCCESSFULLY_UPDATED, componentInstanceId); + 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)); + } + } + @POST @Path("/{componentType}/{componentId}/resource/interfaceOperation") @Consumes(MediaType.APPLICATION_JSON) -- cgit 1.2.3-korg