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 +++++ .../operations/NodeTemplateOperation.java | 70 ++++++++- .../operations/ToscaOperationFacade.java | 4 + .../operations/NodeTemplateOperationTest.java | 52 ++++++- .../operations/ToscaOperationFacadeTest.java | 16 +- catalog-ui/src/app/models/requirement.ts | 2 + .../req-capabilities-tab.component.html | 4 +- .../req-capabilities-tab.component.ts | 10 +- .../requirement-list.component.html | 11 ++ .../requirement-list/requirement-list.component.ts | 21 ++- .../component-instance.service.ts | 7 +- .../log/enums/LoggerSupportabilityActions.java | 1 + .../elements/RequirementDataDefinition.java | 173 ++------------------- .../elements/RequirementDataDefinitionTest.java | 42 +---- 18 files changed, 387 insertions(+), 216 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 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); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperation.java index df1f8fd8bf..3cd46ba846 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperation.java @@ -857,8 +857,10 @@ public class NodeTemplateOperation extends BaseOperation { calculatedRequirements.forEach((key, value) -> { Map mapByType = value.getMapToscaDataDefinition(); - mapByType.forEach((key1, value1) -> value1.getListToscaDataDefinition().forEach(req -> { + mapByType.forEach((key1, value1) -> value1.getListToscaDataDefinition().stream() + .filter(RequirementDataDefinition::isExternal).forEach(req -> { req.addToPath(componentInstance.getUniqueId()); + req.setExternal(false); allCalculatedReq.add(key1, req); })); }); @@ -927,6 +929,72 @@ public class NodeTemplateOperation extends BaseOperation { } return StorageOperationStatus.OK; } + + public StorageOperationStatus updateComponentInstanceRequirement(String componentId, String componentInstanceUniqueId, RequirementDataDefinition requirementDataDefinition) { + Either containerVEither = janusGraphDao + .getVertexById(componentId, JsonParseFlagEnum.ParseAll); + if (containerVEither.isRight()) { + JanusGraphOperationStatus error = containerVEither.right().value(); + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FETCH_CONTAINER_VERTEX_ERROR, componentId, error); + return StorageOperationStatus.GENERAL_ERROR; + } + GraphVertex containerV = containerVEither.left().value(); + return updateComponentInstanceRequirement(componentId, componentInstanceUniqueId, requirementDataDefinition, containerV); + } + + private StorageOperationStatus updateComponentInstanceRequirement(String componentId, String componentInstanceUniqueId, RequirementDataDefinition requirementDataDefinition, GraphVertex containerV) { + Either>, StorageOperationStatus> existingReqs = getCalculatedRequirements(componentId); + if (existingReqs.isRight()) { + return existingReqs.right().value(); + } + MapListRequirementDataDefinition componentInstanceRequirementsMap = existingReqs.left().value().getRight().get(componentInstanceUniqueId); + if (componentInstanceRequirementsMap == null) { + return StorageOperationStatus.NOT_FOUND; + } + ListRequirementDataDefinition listRequirementDataDefinition = componentInstanceRequirementsMap.getMapToscaDataDefinition().get(requirementDataDefinition.getCapability()); + + listRequirementDataDefinition.getListToscaDataDefinition().stream() + .filter(e -> requirementDataDefinition.getOwnerId().equals(e.getOwnerId()) && requirementDataDefinition.getName().equals(e.getName())) + .forEach(r -> r.setExternal(requirementDataDefinition.isExternal())); + + return updateCalculatedReqOnGraph(componentId, containerV, existingReqs); + } + + private Either>, StorageOperationStatus> getCalculatedRequirements(String componentId) { + Either>, StorageOperationStatus> result = null; + Either containerVEither = janusGraphDao + .getVertexById(componentId, JsonParseFlagEnum.ParseAll); + if (containerVEither.isRight()) { + JanusGraphOperationStatus error = containerVEither.right().value(); + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FETCH_CONTAINER_VERTEX_ERROR, componentId, error); + result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(error)); + } + if (result == null) { + GraphVertex containerV = containerVEither.left().value(); + result = fetchContainerCalculatedRequirement(containerV, EdgeLabelEnum.CALCULATED_REQUIREMENTS); + } + return result; + } + + private StorageOperationStatus updateCalculatedReqOnGraph(String componentId, GraphVertex containerV, Either>, StorageOperationStatus> reqResult + ) { + containerV.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis()); + Either updateElement = janusGraphDao.updateVertex(containerV); + if (updateElement.isRight()) { + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update topology template {} with new relations error {}. ", componentId, updateElement.right().value()); + return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updateElement.right().value()); + } + + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Update calculated requirement for container {}", containerV.getUniqueId()); + Either status = updateOrCopyOnUpdate(reqResult.left().value().getLeft(), containerV, EdgeLabelEnum.CALCULATED_REQUIREMENTS); + if (status.isRight()) { + JanusGraphOperationStatus error = status.right().value(); + CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to update calculated requiremnt for container {} error {}", containerV.getUniqueId(), error); + return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(error); + } + return StorageOperationStatus.OK; + } + private StorageOperationStatus addComponentInstanceToscaDataToNodeTypeContainer(NodeType originNodeType, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java index aa03d761bf..dc9174e464 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java @@ -2586,6 +2586,10 @@ public class ToscaOperationFacade { .map(instanceCapProps -> topologyTemplateOperation.updateComponentInstanceCapabilityProperties(containerComponent, componentInstanceUniqueId, instanceCapProps)) .orElse(StorageOperationStatus.NOT_FOUND); } + + public StorageOperationStatus updateComponentInstanceRequirement(String containerComponentId, String componentInstanceUniqueId, RequirementDataDefinition requirementDataDefinition) { + return nodeTemplateOperation.updateComponentInstanceRequirement(containerComponentId, componentInstanceUniqueId, requirementDataDefinition); + } public StorageOperationStatus updateComponentInstanceInterfaces(Component containerComponent, String componentInstanceUniqueId) { MapInterfaceDataDefinition mapInterfaceDataDefinition = diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperationTest.java index 1455d1e984..aea07799b2 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperationTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperationTest.java @@ -32,6 +32,10 @@ package org.openecomp.sdc.be.model.jsonjanusgraph.operations; import com.google.common.collect.Lists; import fj.data.Either; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraphVertex; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -46,9 +50,9 @@ import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao; import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.datatypes.elements.*; +import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.model.*; -import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; @@ -56,6 +60,7 @@ import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -286,6 +291,51 @@ public class NodeTemplateOperationTest extends ModelTestBase { result = operation.generateCustomizationUUIDOnInstanceGroup(componentId, instanceId, groupInstances); Assert.assertEquals(StorageOperationStatus.OK, result); } + + @Test + public void testUpdateComponentInstanceRequirement() { + String componentId = ""; + String componentInstanceId = "requirementOwnerId"; + + GraphVertex graphVertex = new GraphVertex(); + graphVertex.setUniqueId("uniqueId"); + when(janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll)).thenReturn(Either.left(graphVertex)); + when(janusGraphDao.updateVertex(graphVertex)).thenReturn(Either.left(graphVertex)); + + MapListRequirementDataDefinition mapListRequirementDataDefinition = new MapListRequirementDataDefinition(); + mapListRequirementDataDefinition.add(requirement.getCapability(), requirement); + Map mapOfRequirements = new HashMap<>(); + mapOfRequirements.put(requirement.getOwnerId(), mapListRequirementDataDefinition); + GraphVertex childVertex = new GraphVertex(); + childVertex.setJson(mapOfRequirements); + when(janusGraphDao.getChildVertex(graphVertex, EdgeLabelEnum.CALCULATED_REQUIREMENTS, JsonParseFlagEnum.ParseJson)).thenReturn(Either.left(childVertex)); + + JanusGraphVertex outVertex = Mockito.mock(JanusGraphVertex.class); + Edge edge = Mockito.mock(Edge.class); + when(edge.outVertex()).thenReturn(outVertex); + Iterator edgeIterator = new Iterator() { + private int counter = 0; + @Override + public boolean hasNext() { + return counter++ < 1; + } + + @Override + public Edge next() { + return edge; + } + }; + String outId = (String) janusGraphDao + .getProperty((JanusGraphVertex) outVertex, GraphPropertyEnum.UNIQUE_ID.getProperty()); + when(janusGraphDao.getProperty(outVertex, GraphPropertyEnum.UNIQUE_ID.getProperty())).thenReturn("uniqueId"); + when(janusGraphDao.updateVertex(childVertex)).thenReturn(Either.left(childVertex)); + JanusGraphVertex janusGraphVertex = Mockito.mock(JanusGraphVertex.class); + childVertex.setVertex(janusGraphVertex); + when(janusGraphVertex.edges(Direction.IN, EdgeLabelEnum.CALCULATED_REQUIREMENTS.name())).thenReturn(edgeIterator); + + StorageOperationStatus result = operation.updateComponentInstanceRequirement(componentId, componentInstanceId, requirement); + assertEquals(StorageOperationStatus.OK, result); + } private ComponentInstance createCompInstance() { ComponentInstance componentInstance = new ComponentInstance(); diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java index 1c730e5718..0aaae48dc8 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java @@ -37,6 +37,7 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.ArgumentMatchers; import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; @@ -70,7 +71,7 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition; - +import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; import static org.assertj.core.api.Assertions.assertThat; import java.util.HashMap; @@ -718,6 +719,19 @@ public class ToscaOperationFacadeTest { .addComponentInstanceToTopologyTemplate(any(), any(), eq("1"), eq(componentInstance), eq(false), eq(user)); } + @Test + public void testUpdateComponentInstanceRequirement() { + String containerComponentId = "containerComponentId"; + String componentInstanceUniqueId= "componentInstanceUniqueId"; + RequirementDataDefinition requirementDataDefinition= Mockito.mock(RequirementDataDefinition.class); + + when(nodeTemplateOperationMock.updateComponentInstanceRequirement(containerComponentId, componentInstanceUniqueId, requirementDataDefinition)).thenReturn(StorageOperationStatus.OK); + StorageOperationStatus result = testInstance.updateComponentInstanceRequirement(containerComponentId, componentInstanceUniqueId, requirementDataDefinition); + assertEquals(StorageOperationStatus.OK, result); + verify(nodeTemplateOperationMock, times(1)).updateComponentInstanceRequirement(containerComponentId, componentInstanceUniqueId, requirementDataDefinition); + + } + private Either associatePolicyToComponentWithStatus(StorageOperationStatus status) { PolicyDefinition policy = new PolicyDefinition(); String componentId = "componentId"; diff --git a/catalog-ui/src/app/models/requirement.ts b/catalog-ui/src/app/models/requirement.ts index d58aabd457..ade2f3cee1 100644 --- a/catalog-ui/src/app/models/requirement.ts +++ b/catalog-ui/src/app/models/requirement.ts @@ -53,6 +53,7 @@ export class Requirement implements RequirementCapabilityModel{ leftOccurrences:string; minOccurrences:string | number; maxOccurrences:string; + external:boolean; //custom filterTerm:string; @@ -70,6 +71,7 @@ export class Requirement implements RequirementCapabilityModel{ this.leftOccurrences = requirement.leftOccurrences; this.minOccurrences = requirement.minOccurrences; this.maxOccurrences = requirement.maxOccurrences; + this.external = requirement.external; this.initFilterTerm(); } diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html index 27e05ec1f0..c73f69734f 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.html @@ -10,7 +10,7 @@
- +
@@ -28,7 +28,7 @@ - + diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts index 03697b38f2..7c91cbc4b8 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/req-capabilities-tab.component.ts @@ -122,10 +122,12 @@ export class ReqAndCapabilitiesTabComponent implements OnInit, OnDestroy { this.requirementsInstancesMap = new InstanceRequirementsMap(); _.forEach(this.requirements, (requirement:Requirement) => { - if (this.requirementsInstancesMap[requirement.ownerName]) { - this.requirementsInstancesMap[requirement.ownerName] = this.requirementsInstancesMap[requirement.ownerName].concat(requirement); - } else { - this.requirementsInstancesMap[requirement.ownerName] = new Array(requirement); + if(this.isComponentInstanceSelected || requirement.external){ + if (this.requirementsInstancesMap[requirement.ownerName]) { + this.requirementsInstancesMap[requirement.ownerName] = this.requirementsInstancesMap[requirement.ownerName].concat(requirement); + } else { + this.requirementsInstancesMap[requirement.ownerName] = new Array(requirement); + } } }); } diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html index 8292729cf8..291b103344 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html @@ -13,6 +13,17 @@ +
+ + +
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts index e167c47dcc..3716ef0af0 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.ts @@ -2,6 +2,8 @@ import { Component, Input } from '@angular/core'; import { Component as TopologyTemplate, RelationshipModel, Relationship, Requirement } from "app/models"; import { CompositionService } from "app/ng2/pages/composition/composition.service"; import { ResourceNamePipe } from "app/ng2/pipes/resource-name.pipe"; +import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service"; +import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service"; @Component({ selector: 'requirement-list', @@ -11,10 +13,12 @@ export class RequirementListComponent { @Input() component: TopologyTemplate; @Input() requirements: Array; @Input() isInstanceSelected:boolean; + @Input() isViewOnly: boolean; + readonly:boolean; - - constructor(private compositionService: CompositionService) { } - + constructor(private compositionService: CompositionService, + private workspaceService: WorkspaceService, + private componentInstanceServiceNg2: ComponentInstanceServiceNg2) {} public getRelation = (requirement:any):any => { if (this.isInstanceSelected && this.component.componentInstancesRelations) { @@ -36,5 +40,16 @@ export class RequirementListComponent { return null; }; + onMarkAsExternal(requirement:Requirement) { + if (requirement.external){ + requirement.external = false; + } else { + requirement.external = true; + } + this.componentInstanceServiceNg2.updateInstanceRequirement(this.workspaceService.metadata.getTypeUrl(), this.workspaceService.metadata.uniqueId, this.component.uniqueId, requirement).subscribe((response:any) => { + }, (error) => { console.log("An error has occured setting external: ", error); });; + + } + }; diff --git a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts index af6ed9d4b0..74ced7d4bf 100644 --- a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts +++ b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts @@ -20,7 +20,7 @@ import {Injectable, Inject} from '@angular/core'; import { Observable } from 'rxjs/Observable'; -import {PropertyFEModel, PropertyBEModel} from "app/models"; +import {PropertyFEModel, PropertyBEModel, Requirement} from "app/models"; import {CommonUtils, ComponentType, ServerTypeUrl, ComponentInstanceFactory} from "app/utils"; import {Component, ComponentInstance, Capability, PropertyModel, ArtifactGroupModel, ArtifactModel, AttributeModel, IFileDownload} from "app/models"; import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config"; @@ -125,6 +125,11 @@ export class ComponentInstanceServiceNg2 { }) } + updateInstanceRequirement(componentType: string, componentId: string, componentInstanceId: string, requirement: Requirement): Observable { + return this.http.put(this.baseUrl + componentType + componentId + '/componentInstances/' + componentInstanceId + '/requirement/' + requirement.capability + + '/requirementName/' + requirement.name, requirement); + } + updateInstanceInputs(component: Component, componentInstanceId: string, inputs: PropertyBEModel[]): Observable { return this.http.post>(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstance/' + componentInstanceId + '/inputs', inputs) diff --git a/common-app-logging/src/main/java/org/openecomp/sdc/common/log/enums/LoggerSupportabilityActions.java b/common-app-logging/src/main/java/org/openecomp/sdc/common/log/enums/LoggerSupportabilityActions.java index 93fddf5d2e..de4f78e13a 100644 --- a/common-app-logging/src/main/java/org/openecomp/sdc/common/log/enums/LoggerSupportabilityActions.java +++ b/common-app-logging/src/main/java/org/openecomp/sdc/common/log/enums/LoggerSupportabilityActions.java @@ -76,6 +76,7 @@ public enum LoggerSupportabilityActions { GENERATE_TOSCA("GENERATE TOSCA"), UPDATE_GROUP_MEMBERS("UPDATE GROUP MEMBERS"), UPDATE_INSTANCE_CAPABILITY_PROPERTY("UPDATE INSTANCE CAPABILITY PROPERTY"), + UPDATE_INSTANCE_REQUIREMENT("UPDATE INSTANCE REQUIREMENT"), UPDATE_POLICY_TARGET("UPDATE POLICY TARGET"), UPDATE_POLICIES_PROPERTIES("UPDATE POLICIES PROPERTIES"); diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java index f8402b7a3a..4b7b6aa413 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java @@ -21,6 +21,10 @@ package org.openecomp.sdc.be.datatypes.elements; import com.google.common.collect.Lists; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; @@ -30,11 +34,17 @@ import java.util.List; /** * Represents the requirement of the component or component instance */ +@EqualsAndHashCode +@ToString public class RequirementDataDefinition extends ToscaDataDefinition { public static final String MIN_OCCURRENCES = "0"; public static final String MAX_OCCURRENCES = "UNBOUNDED"; public static final String MAX_DEFAULT_OCCURRENCES = "1"; + + @Getter + @Setter + public boolean external = false; /** * The default constructor initializing limits of the occurrences @@ -69,6 +79,7 @@ public class RequirementDataDefinition extends ToscaDataDefinition { this.setPath(Lists.newArrayList(other.getPath())); } this.setSource(other.getSource()); + this.setExternal(other.isExternal()); } /** @@ -218,166 +229,4 @@ public class RequirementDataDefinition extends ToscaDataDefinition { setPath(path); } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - String name = getName(); - String uniqueId = getUniqueId(); - String capability = getCapability(); - String node = getNode(); - String relationship = getRelationship(); - String ownerId = getOwnerId(); - String ownerName = getOwnerName(); - String minOccurrences = getMinOccurrences(); - String maxOccurrences = getMaxOccurrences(); - String leftOccurrences = getLeftOccurrences(); - - List path = this.getPath(); - String source = getSource(); - - result = prime * result + ((capability == null) ? 0 : capability.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((node == null) ? 0 : node.hashCode()); - result = prime * result + ((ownerId == null) ? 0 : ownerId.hashCode()); - result = prime * result + ((ownerName == null) ? 0 : ownerName.hashCode()); - result = prime * result + ((relationship == null) ? 0 : relationship.hashCode()); - result = prime * result + ((uniqueId == null) ? 0 : uniqueId.hashCode()); - result = prime * result + ((minOccurrences == null) ? 0 : minOccurrences.hashCode()); - result = prime * result + ((maxOccurrences == null) ? 0 : maxOccurrences.hashCode()); - result = prime * result + ((leftOccurrences == null) ? 0 : leftOccurrences.hashCode()); - result = prime * result + ((path == null) ? 0 : path.hashCode()); - result = prime * result + ((source == null) ? 0 : source.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - RequirementDataDefinition other = (RequirementDataDefinition) obj; - - String name = getName(); - String uniqueId = getUniqueId(); - String capability = getCapability(); - String node = getNode(); - String relationship = getRelationship(); - String ownerId = getOwnerId(); - String ownerName = getOwnerName(); - String minOccurrences = getMinOccurrences(); - String maxOccurrences = getMaxOccurrences(); - String leftOccurrences = getLeftOccurrences(); - List path = this.getPath(); - String source = getSource(); - - if (capability == null) { - if (other.getCapability() != null) { - return false; - } - } else if (!capability.equals(other.getCapability())) { - return false; - } - if (name == null) { - if (other.getName() != null) { - return false; - } - } else if (!name.equals(other.getName())) { - return false; - } - if (node == null) { - if (other.getNode() != null) { - return false; - } - } else if (!node.equals(other.getNode())) { - return false; - } - if (ownerId == null) { - if (other.getOwnerId() != null) { - return false; - } - } else if (!ownerId.equals(other.getOwnerId())) { - return false; - } - if (ownerName == null) { - if (other.getOwnerName() != null) { - return false; - } - } else if (!ownerName.equals(other.getOwnerName())) { - return false; - } - if (relationship == null) { - if (other.getRelationship() != null) { - return false; - } - } else if (!relationship.equals(other.getRelationship())) { - return false; - } - if (uniqueId == null) { - if (other.getUniqueId() != null) { - return false; - } - } else if (!uniqueId.equals(other.getUniqueId())) { - return false; - } - if (minOccurrences == null) { - if (other.getMinOccurrences() != null) { - return false; - } - } else if (!minOccurrences.equals(other.getMinOccurrences())) { - return false; - } - if (maxOccurrences == null) { - if (other.getMaxOccurrences() != null) { - return false; - } - } else if (!maxOccurrences.equals(other.getMaxOccurrences())) { - return false; - } - if (leftOccurrences == null) { - if (other.getLeftOccurrences() != null) { - return false; - } - } else if (!leftOccurrences.equals(other.getLeftOccurrences())) { - return false; - } - if (path == null) { - if (other.getPath() != null) { - return false; - } - } else if (!path.equals(other.getPath())) { - return false; - } - if (source == null) { - return other.getSource() == null; - } else { - return source.equals(other.getSource()); - } - } - - @Override - public String toString() { - String name = getName(); - String uniqueId = getUniqueId(); - String capability = getCapability(); - String node = getNode(); - String relationship = getRelationship(); - String ownerId = getOwnerId(); - String ownerName = getOwnerName(); - String minOccurrences = getMinOccurrences(); - String maxOccurrences = getMaxOccurrences(); - String leftOccurrences = getLeftOccurrences(); - List path = this.getPath(); - String source = getSource(); - - return "RequirementDefinition [uniqueId=" + uniqueId + ", name=" + name + ", capability=" + capability + ", node=" + node + ", relationship=" + relationship + ", ownerId=" + ownerId + ", ownerName=" + ownerName + ", minOccurrences=" - + minOccurrences + ", maxOccurrences=" + maxOccurrences + ",leftOccurrences=" + leftOccurrences + ", path=" + path + ", source=" + source + "]"; - } - } diff --git a/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinitionTest.java b/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinitionTest.java index 6e13054201..1fbe448959 100644 --- a/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinitionTest.java +++ b/common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinitionTest.java @@ -22,7 +22,8 @@ package org.openecomp.sdc.be.datatypes.elements; import org.junit.Assert; import org.junit.Test; - +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import java.util.List; @@ -338,43 +339,4 @@ public class RequirementDataDefinitionTest { testSubject.addToPath(elementInPath); } - - @Test - public void testHashCode() throws Exception { - RequirementDataDefinition testSubject; - int result; - - // default test - testSubject = createTestSubject(); - result = testSubject.hashCode(); - } - - - @Test - public void testEquals() throws Exception { - RequirementDataDefinition testSubject; - Object obj = null; - boolean result; - - // test 1 - testSubject = createTestSubject(); - obj = null; - result = testSubject.equals(obj); - Assert.assertEquals(false, result); - result = testSubject.equals(testSubject); - Assert.assertEquals(true, result); - result = testSubject.equals(createTestSubject()); - Assert.assertEquals(true, result); - } - - - @Test - public void testToString() throws Exception { - RequirementDataDefinition testSubject; - String result; - - // default test - testSubject = createTestSubject(); - result = testSubject.toString(); - } } -- cgit 1.2.3-korg