From 3e9a9769dd21f0b16b3f238e42349cba3b1a78de Mon Sep 17 00:00:00 2001 From: vasraz Date: Fri, 4 Sep 2020 15:27:00 +0100 Subject: Enable selection of requirements Instead of all requirements of the component instances in a component being exposed outside the component, this change will enable the component designer to specifiy which should be exposed outside the component and which are to be internal to the component Change-Id: Ib063f7b8b0aca94896e78a46f069725bae3d494d Issue-ID: SDC-2771 Signed-off-by: MichaelMorris Signed-off-by: Vasyl Razinkov --- .../impl/ComponentInstanceBusinessLogic.java | 60 +++++++++++++++++++++ .../sdc/be/servlets/ComponentInstanceServlet.java | 63 ++++++++++++++++++++++ .../be/tosca/CapabilityRequirementConverter.java | 2 +- .../impl/ComponentInstanceBusinessLogicTest.java | 30 +++++++++++ .../be/servlets/ComponentInstanceServletTest.java | 35 ++++++++++++ 5 files changed, 189 insertions(+), 1 deletion(-) (limited to 'catalog-be/src') 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 ce1eed1a4c..236db5fe40 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 @@ -2700,6 +2700,66 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR); } } + + public Either updateInstanceRequirement(ComponentTypeEnum componentTypeEnum, String containerComponentId, String componentInstanceUniqueId, String capabilityType, String capabilityName, + RequirementDefinition requirementDef, String userId) { + + Either resultOp = null; + + validateUserExists(userId); + if (componentTypeEnum == null) { + BeEcompErrorManager.getInstance().logInvalidInputError("updateInstanceRequirement", INVALID_COMPONENT_TYPE, ErrorSeverity.INFO); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.NOT_ALLOWED)); + } + Either getResourceResult = toscaOperationFacade.getToscaFullElement(containerComponentId); + + if (getResourceResult.isRight()) { + log.debug(FAILED_TO_RETRIEVE_COMPONENT_COMPONENT_ID, containerComponentId); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); + } + Component containerComponent = getResourceResult.left().value(); + + if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) { + log.info("Restricted operation for user: {} on component {}", userId, containerComponentId); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); + } + Either resourceInstanceStatus = getResourceInstanceById(containerComponent, componentInstanceUniqueId); + if (resourceInstanceStatus.isRight()) { + return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE, componentInstanceUniqueId, containerComponentId)); + } + // lock resource + StorageOperationStatus lockStatus = graphLockOperation.lockComponent(containerComponentId, componentTypeEnum.getNodeType()); + if (lockStatus != StorageOperationStatus.OK) { + log.debug("Failed to lock component {}", containerComponentId); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockStatus))); + } + + try { + StorageOperationStatus updateRequirementStatus = toscaOperationFacade.updateComponentInstanceRequirement(containerComponentId, componentInstanceUniqueId, requirementDef); + if (updateRequirementStatus != StorageOperationStatus.OK) { + log.debug("Failed to update component instance requirement on instance {} in container {}", componentInstanceUniqueId, containerComponentId); + return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(updateRequirementStatus))); + } + Either updateContainerRes = toscaOperationFacade.updateComponentInstanceMetadataOfTopologyTemplate(containerComponent); + + if (updateContainerRes.isRight()) { + ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForResourceInstanceProperty(updateContainerRes.right().value()); + resultOp = Either.right(componentsUtils.getResponseFormatForResourceInstanceProperty(actionStatus, "")); + return resultOp; + } + resultOp = Either.left(requirementDef); + return resultOp; + + } finally { + if (resultOp == null || resultOp.isRight()) { + janusGraphDao.rollback(); + } else { + janusGraphDao.commit(); + } + // unlock resource + graphLockOperation.unlockComponent(containerComponentId, componentTypeEnum.getNodeType()); + } + } public Either, ResponseFormat> updateInstanceCapabilityProperties(ComponentTypeEnum componentTypeEnum, String containerComponentId, String componentInstanceUniqueId, String capabilityType, String capabilityName, List properties, String userId) { 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 4f3120aba2..5c3bd859be 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 @@ -88,9 +88,11 @@ import org.openecomp.sdc.be.model.ComponentInstanceInput; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.PropertyConstraint; import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; +import org.openecomp.sdc.be.model.RequirementDefinition; import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.datastructure.Wrapper; @@ -1095,6 +1097,67 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet { throw e; } } + + @PUT + @Path("/{containerComponentType}/{containerComponentId}/componentInstances/{componentInstanceUniqueId}/requirement/{capabilityType}/requirementName/{requirementName}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Update Instance Requirement", method = "PUT", + summary = "Returns updated requirement", responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))), + @ApiResponse(responseCode = "200", description = "Resource instance requirement updated"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "404", description = "Component/Component Instance/Requirement - not found")}) + @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) + public Response updateInstanceRequirement( + @PathParam("containerComponentType") final String containerComponentType, + @PathParam("containerComponentId") final String containerComponentId, + @PathParam("componentInstanceUniqueId") final String componentInstanceUniqueId, + @PathParam("capabilityType") final String capabilityType, + @PathParam("requirementName") final String requirementName, + @Parameter(description = "Instance capabilty requirement to update", required = true) String data, + @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug(START_HANDLE_REQUEST_OF, url); + loggerSupportability.log(LoggerSupportabilityActions.UPDATE_INSTANCE_REQUIREMENT, StatusCode.STARTED,"Starting to update requirement {} in component instance {} by {}", requirementName, componentInstanceUniqueId, userId ); + try { + + log.debug(START_HANDLE_REQUEST_OF, url); + + ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType); + if (componentInstanceBusinessLogic == null) { + log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType)); + } + + Either mappedRequirementDataEither = getMappedRequirementData(data, new User(userId), componentTypeEnum); + if(mappedRequirementDataEither.isRight()) { + log.debug("Failed to update requirements"); + return buildErrorResponse(mappedRequirementDataEither.right().value()); + } + RequirementDefinition requirementDef = mappedRequirementDataEither.left().value(); + + Either response = componentInstanceBusinessLogic.updateInstanceRequirement(componentTypeEnum, containerComponentId, componentInstanceUniqueId, capabilityType, requirementName, requirementDef, userId); + + if (response.isRight()) { + return buildErrorResponse(response.right().value()); + } + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), response.left().value()); + + } catch (ComponentException e) { + throw e; + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update component instance requirement"); + log.debug("Update component instance requirement with exception", e); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + private Either getMappedRequirementData(String inputJson, User user, + ComponentTypeEnum componentTypeEnum){ + return getComponentsUtils().convertJsonToObjectUsingObjectMapper(inputJson, user, RequirementDefinition.class, AuditingActionEnum.GET_TOSCA_MODEL, componentTypeEnum); + } @POST @Path("/{containerComponentType}/{containerComponentId}/serviceProxy") diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java index 9a55fb885c..3e4907721d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java @@ -307,7 +307,7 @@ public class CapabilityRequirementConverter { Either, ToscaError> result = null; for (Map.Entry> entry : requirements.entrySet()) { Optional failedToAddRequirement = entry.getValue() - .stream() + .stream().filter(RequirementDefinition::isExternal) .filter(r->!addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(r.getName(), r.getParentName(), ""), r.getPreviousName(), r.getOwnerId(), r.getPath())) .findAny(); if(failedToAddRequirement.isPresent()){ diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java index d585c6f77a..12ffe1c193 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java @@ -1143,6 +1143,36 @@ class ComponentInstanceBusinessLogicTest { componentInstanceUniqueId, capabilityType, capabilityName, properties, userId); assertNotNull(result); } + + @Test + void testUpdateInstanceRequirement() { + ComponentInstanceBusinessLogic testSubject; + ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.RESOURCE; + createComponents(); + String userId = "userId"; + resource.setLastUpdaterUserId(userId); + String containerComponentId = resource.getUniqueId(); + String componentInstanceUniqueId = TO_INSTANCE_ID; + String capabilityType = ""; + String capabilityName = ""; + RequirementDefinition requirementDef = new RequirementDefinition(); + + Either result; + + when(toscaOperationFacade.getToscaFullElement(containerComponentId)).thenReturn(Either.left(resource)); + testSubject = createTestSubject(); + when(toscaOperationFacade.updateComponentInstanceRequirement(containerComponentId, TO_INSTANCE_ID, requirementDef)).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacade.updateComponentInstanceMetadataOfTopologyTemplate(resource)).thenReturn(Either.left(resource)); + when(graphLockOperation.unlockComponent(Mockito.anyString(), eq(NodeTypeEnum.Resource))) + .thenReturn(StorageOperationStatus.OK); + when(graphLockOperation.lockComponent(Mockito.anyString(), eq(NodeTypeEnum.Resource))) + .thenReturn(StorageOperationStatus.OK); + + result = testSubject.updateInstanceRequirement(componentTypeEnum, containerComponentId, + componentInstanceUniqueId, capabilityType, capabilityName, requirementDef, userId); + assertEquals(requirementDef, result.left().value()); + + } @Test void testCopyComponentInstanceWrongUserId() { diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentInstanceServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentInstanceServletTest.java index d801314c79..0eee7a1238 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentInstanceServletTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentInstanceServletTest.java @@ -39,6 +39,7 @@ import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import javax.ws.rs.Path; import javax.ws.rs.client.Entity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -66,6 +67,7 @@ import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.ComponentInstanceInput; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; +import org.openecomp.sdc.be.model.RequirementDefinition; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.user.UserBusinessLogic; @@ -433,4 +435,37 @@ public class ComponentInstanceServletTest extends JerseyTest { .header("USER_ID", USER_ID).post(Entity.entity(inputs, MediaType.APPLICATION_JSON)); assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND_404); } + + @Test + public void testUpdateInstanceRequirement(){ + + String containerComponentType = "services"; + String componentId = "componentId"; + String componentInstanceId = "componentInstanceIdInstanceId"; + String capabilityType = "capabilityType"; + String requirementName = "requirementName"; + RequirementDefinition requirementDefinition = new RequirementDefinition(); + ObjectMapper mapper = new ObjectMapper(); + String requirementJson = null; + try { + requirementJson = mapper.writeValueAsString(requirementDefinition); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + String path = "/v1/catalog/" + containerComponentType + "/" + componentId + "/componentInstances/" + + componentInstanceId + "/requirement/" + capabilityType + "/requirementName/" + requirementName; + when(componentsUtils.convertJsonToObjectUsingObjectMapper(eq(requirementJson), any(User.class), eq(RequirementDefinition.class), + eq(AuditingActionEnum.GET_TOSCA_MODEL), eq(ComponentTypeEnum.SERVICE))).thenReturn(Either.left(requirementDefinition)); + when(componentInstanceBusinessLogic.updateInstanceRequirement(ComponentTypeEnum.SERVICE, + componentId, componentInstanceId, capabilityType, requirementName, requirementDefinition, USER_ID)) + .thenReturn(Either.left(requirementDefinition)); + when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat); + when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200); + + Response response = target() + .path(path) + .request(MediaType.APPLICATION_JSON) + .header("USER_ID", USER_ID).put(Entity.entity(requirementDefinition, MediaType.APPLICATION_JSON)); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200); + } } -- cgit 1.2.3-korg