From 5c1f5756bcb5856e2d8b35e3c6ac206f891f8695 Mon Sep 17 00:00:00 2001 From: aribeiro Date: Thu, 19 Nov 2020 13:28:43 +0000 Subject: Add support for updating interface operations Allows to update interface operations on a component instance. Issue-ID: SDC-3446 Signed-off-by: aribeiro Signed-off-by: andre.schmid Change-Id: I6a2c44997c04d9d9ea298e3d0bc971da7b137799 --- .../impl/ComponentInstanceBusinessLogic.java | 24 ++- .../ComponentInterfaceOperationBusinessLogic.java | 221 +++++++++++++++++++++ .../impl/InterfaceDefinitionHandler.java | 9 +- .../be/components/impl/ResourceImportManager.java | 3 +- .../ComponentInterfaceOperationServlet.java | 179 +++++++++++++++++ .../be/tosca/InterfacesOperationsConverter.java | 166 ++++++++++------ .../openecomp/sdc/be/tosca/ToscaExportHandler.java | 67 ++++--- .../be/components/ResourceImportManagerTest.java | 29 ++- ...mponentInterfaceOperationBusinessLogicTest.java | 173 ++++++++++++++++ .../components/impl/InputsBusinessLogicTest.java | 8 +- .../tosca/InterfacesOperationsConverterTest.java | 16 +- 11 files changed, 759 insertions(+), 136 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogic.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInterfaceOperationServlet.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogicTest.java (limited to 'catalog-be') 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 7c463ac387..1104621379 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 @@ -349,17 +349,17 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { final OriginTypeEnum originType = resourceInstance.getOriginType(); validateInstanceName(resourceInstance); if (originType == OriginTypeEnum.ServiceProxy) { - origComponent = getOrigComponentForServiceProxy(containerComponent, resourceInstance); - } else if (originType == OriginTypeEnum.ServiceSubstitution){ - origComponent = getOrigComponentForServiceSubstitution(resourceInstance); - } else { - origComponent = getAndValidateOriginComponentOfComponentInstance(containerComponent, resourceInstance); - validateOriginAndResourceInstanceTypes(containerComponent, origComponent, originType); - } - validateResourceInstanceState(containerComponent, origComponent); - overrideFields(origComponent, resourceInstance); - compositionBusinessLogic.validateAndSetDefaultCoordinates(resourceInstance); + origComponent = getOrigComponentForServiceProxy(containerComponent, resourceInstance); + } else if (originType == OriginTypeEnum.ServiceSubstitution) { + origComponent = getOrigComponentForServiceSubstitution(resourceInstance); + } else { + origComponent = getAndValidateOriginComponentOfComponentInstance(containerComponent, resourceInstance); + validateOriginAndResourceInstanceTypes(containerComponent, origComponent, originType); } + validateResourceInstanceState(containerComponent, origComponent); + overrideFields(origComponent, resourceInstance); + compositionBusinessLogic.validateAndSetDefaultCoordinates(resourceInstance); + } return createComponent(needLock, containerComponent,origComponent, resourceInstance, user); } @@ -2444,6 +2444,10 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { ActionStatus actionStatus = ActionStatus.COMPONENT_IS_ARCHIVED; throw new ByActionStatusComponentException(actionStatus, component.getName()); } + final Map componentInterfaces = component.getInterfaces(); + if(MapUtils.isNotEmpty(componentInterfaces)) { + componentInterfaces.forEach(componentInstance::addInterface); + } return component; } 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 new file mode 100644 index 0000000000..e32c51f7da --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogic.java @@ -0,0 +1,221 @@ +/* + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.zone-instance.component.ts + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl; + +import fj.data.Either; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; +import org.openecomp.sdc.be.components.validation.ComponentValidations; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInterface; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.InterfaceDefinition; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; +import org.openecomp.sdc.be.model.operations.api.IElementOperation; +import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; +import org.openecomp.sdc.be.model.operations.api.IGroupOperation; +import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; +import org.openecomp.sdc.be.user.Role; +import org.openecomp.sdc.common.datastructure.Wrapper; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +@org.springframework.stereotype.Component("componentInterfaceOperationBusinessLogic") +public class ComponentInterfaceOperationBusinessLogic extends BaseBusinessLogic { + + private final ComponentValidations componentValidations; + + private static final Logger LOGGER = LoggerFactory.getLogger(ComponentInterfaceOperationBusinessLogic .class); + + @Autowired + public ComponentInterfaceOperationBusinessLogic(final IElementOperation elementDao, + final IGroupOperation groupOperation, + final IGroupInstanceOperation groupInstanceOperation, + final IGroupTypeOperation groupTypeOperation, + final InterfaceOperation interfaceOperation, + final InterfaceLifecycleOperation interfaceLifecycleTypeOperation, + final ArtifactsOperations artifactToscaOperation, + final ComponentValidations componentValidations) { + super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, + interfaceLifecycleTypeOperation, artifactToscaOperation); + this.componentValidations = componentValidations; + } + + public Optional updateComponentInstanceInterfaceOperation(final String componentId, + final String componentInstanceId, + final InterfaceDefinition interfaceDefinition, + final ComponentTypeEnum componentTypeEnum, + final Wrapper errorWrapper, + final boolean shouldLock) + throws BusinessLogicException { + + final Component component = getComponent(componentId); + final Optional componentInstanceOptional = componentValidations + .getComponentInstance(component, componentInstanceId); + ResponseFormat responseFormat; + if (componentInstanceOptional.isEmpty()) { + responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND); + LOGGER.debug("Failed to found 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 List componentInstanceInterfaceList = componentInstancesInterfaceMap + .get(componentInstanceId); + + if (CollectionUtils.isEmpty(componentInstanceInterfaceList)) { + responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND); + LOGGER.debug("Failed to found component instance with id {}, error: {}", + componentInstanceId, responseFormat); + errorWrapper.setInnerElement(responseFormat); + return Optional.empty(); + } + + final Optional optionalOperationDataDefinition = interfaceDefinition + .getOperations().values().stream().findFirst(); + if (optionalOperationDataDefinition.isEmpty()) { + responseFormat = componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND); + LOGGER.debug("Failed to found interface operation on component instance with id {}, error: {}", + componentInstanceId, responseFormat); + errorWrapper.setInnerElement(responseFormat); + return Optional.empty(); + } + final OperationDataDefinition updatedOperationDataDefinition = optionalOperationDataDefinition.get(); + final Optional optionalComponentInstanceInterface = componentInstanceInterfaceList + .stream().filter(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); + LOGGER.debug("Failed to found ComponentInstanceInterface on component instance with id {}, error: {}", + componentInstanceId, responseFormat); + errorWrapper.setInnerElement(responseFormat); + return Optional.empty(); + } + + updateOperationDefinitionImplementation(updatedOperationDataDefinition); + + optionalComponentInstanceInterface.get().getOperations() + .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 + .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(); + } + + final ComponentParametersView componentFilter = new ComponentParametersView(); + componentFilter.disableAll(); + componentFilter.setIgnoreUsers(false); + componentFilter.setIgnoreComponentInstances(false); + componentFilter.setIgnoreInterfaces(false); + componentFilter.setIgnoreComponentInstancesInterfaces(false); + + final Either operationStatusEither = toscaOperationFacade + .updateComponentInstanceMetadataOfTopologyTemplate(component, componentFilter); + + if (operationStatusEither.isRight()) { + janusGraphDao.rollback(); + responseFormat = componentsUtils + .getResponseFormat(ActionStatus.GENERAL_ERROR); + LOGGER.error("Exception occurred when updating Component Instance Topology template {}", 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 User validateUser(final String userId) { + final User user = userValidations.validateUserExists(userId); + userValidations + .validateUserRole(user, Arrays.asList(Role.DESIGNER, Role.ADMIN)); + return user; + } + + private void unlockComponent(final String componentUniqueId, + final ComponentTypeEnum componentType) { + graphLockOperation.unlockComponent(componentUniqueId, componentType.getNodeType()); + } + + private void updateOperationDefinitionImplementation(final OperationDataDefinition updatedOperationDataDefinition) { + final ArtifactDataDefinition artifactInfo = new ArtifactDataDefinition(); + artifactInfo.setArtifactName( + String.format("'%s'", updatedOperationDataDefinition.getImplementation().getArtifactName()) + ); + updatedOperationDataDefinition.setImplementation(artifactInfo); + } +} 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 aeb4376c15..71005ef0f0 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 @@ -38,6 +38,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; +import java.util.UUID; import java.util.stream.Collectors; import org.apache.commons.collections.MapUtils; import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; @@ -172,9 +173,13 @@ public class InterfaceDefinitionHandler { private OperationDataDefinition createOperation(final String operationName, final Map operationDefinitionMap) { final OperationDataDefinition operation = new OperationDataDefinition(); + operation.setUniqueId(UUID.randomUUID().toString()); operation.setName(operationName); - handleOperationImplementation(operationDefinitionMap).ifPresent(operation::setImplementation); + operation.setImplementation( + handleOperationImplementation(operationDefinitionMap) + .orElse(new ArtifactDataDefinition()) + ); if (operationDefinitionMap.containsKey(INPUTS.getElementName())) { final Map interfaceInputs = (Map) operationDefinitionMap.get(INPUTS.getElementName()); @@ -189,6 +194,8 @@ public class InterfaceDefinitionHandler { final ListDataDefinition inputs = new ListDataDefinition<>(); for (final Entry interfaceInput : interfaceInputs.entrySet()) { final OperationInputDefinition operationInput = new OperationInputDefinition(); + operationInput.setUniqueId(UUID.randomUUID().toString()); + operationInput.setInputId(operationInput.getUniqueId()); operationInput.setName(interfaceInput.getKey()); if (interfaceInput.getValue() instanceof Map) { final LinkedHashMap inputPropertyValue = 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 b96e4e58e2..6137a3ffca 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 @@ -375,7 +375,8 @@ public class ResourceImportManager { log.info("error when creating interface:{}, for resource:{}", interfaceNameValue.getKey(), resource.getName()); } else { - moduleInterfaces.put(interfaceNameValue.getKey(), eitherInterface.left().value()); + final InterfaceDefinition interfaceDefinition = eitherInterface.left().value(); + moduleInterfaces.put(interfaceNameValue.getKey(), interfaceDefinition); } } 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 new file mode 100644 index 0000000000..c2e668c049 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInterfaceOperationServlet.java @@ -0,0 +1,179 @@ +/* + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nordix Foundation. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.servlets; + +import fj.data.Either; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +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 java.io.IOException; +import java.util.Optional; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.commons.io.IOUtils; +import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ComponentInterfaceOperationBusinessLogic; +import org.openecomp.sdc.be.components.impl.ResourceImportManager; +import org.openecomp.sdc.be.components.impl.aaf.AafPermission; +import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +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.ComponentInstance; +import org.openecomp.sdc.be.model.InterfaceDefinition; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.datastructure.Wrapper; +import org.openecomp.sdc.exception.ResponseFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +@Path("/v1/catalog/{componentType}/{componentId}/componentInstance/{componentInstanceId}/interfaceOperation") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Controller +public class ComponentInterfaceOperationServlet extends AbstractValidationsServlet { + + private static final Logger LOGGER = LoggerFactory.getLogger(ComponentInterfaceOperationServlet.class); + private static final String START_HANDLE_REQUEST_OF = "Start handle {} request of {}"; + private static final String MODIFIER_ID_IS = "modifier id is {}"; + + private static final String FAILED_TO_UPDATE_INTERFACE_OPERATION = + "failed to update Interface Operation on component instance {}"; + private static final String UPDATE_INTERFACE_OPERATION = "Update Interface Operation on Component Instance"; + 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 final ComponentInterfaceOperationBusinessLogic componentInterfaceOperationBusinessLogic; + + @Autowired + public ComponentInterfaceOperationServlet(final UserBusinessLogic userBusinessLogic, + final ComponentInstanceBusinessLogic componentInstanceBL, + final ComponentsUtils componentsUtils, + final ServletUtils servletUtils, + final ResourceImportManager resourceImportManager, + final ComponentInterfaceOperationBusinessLogic componentInterfaceOperationBusinessLogic) { + super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager); + this.componentInterfaceOperationBusinessLogic = componentInterfaceOperationBusinessLogic; + } + + @PUT + @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 updateComponentInstanceInterfaceOperation( + @Parameter(description = "valid values: resources / services", + schema = @Schema(allowableValues = { + ComponentTypeEnum.RESOURCE_PARAM_NAME, + ComponentTypeEnum.SERVICE_PARAM_NAME})) + @PathParam("componentType") final 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()); + 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); + 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 + .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()); + } else { + LOGGER.debug(INTERFACE_OPERATION_SUCCESSFULLY_UPDATED, componentInstanceId); + response = 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); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + private Optional getMappedInterfaceData(final String inputJson, + final User user, + final ComponentTypeEnum componentTypeEnum) { + final Either uiComponentEither = + getComponentsUtils().convertJsonToObjectUsingObjectMapper(inputJson, user, + UiComponentDataTransfer.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, componentTypeEnum); + return uiComponentEither.left().value().getInterfaces().values().stream().findFirst(); + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java index 8fb835e0b9..8d35517d92 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java @@ -21,6 +21,7 @@ import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INPUTS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.OPERATIONS; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import java.util.Collections; @@ -32,6 +33,7 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; import org.openecomp.sdc.be.datatypes.elements.InputDataDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; @@ -150,63 +152,100 @@ public class InterfacesOperationsConverter { final Map dataTypes, final boolean isAssociatedComponent, final boolean isServiceProxyInterface) { - if(MapUtils.isEmpty(interfaces)) { + if (MapUtils.isEmpty(interfaces)) { return null; } - Map toscaInterfaceDefinitions = new HashMap<>(); + final Map toscaInterfaceDefinitions = new HashMap<>(); for (InterfaceDefinition interfaceDefinition : interfaces.values()) { - ToscaInterfaceDefinition toscaInterfaceDefinition = new ToscaInterfaceDefinition(); - final String interfaceType; - if(componentInstance != null && LOCAL_INTERFACE_TYPE.equals(interfaceDefinition.getType())) { - interfaceType = DERIVED_FROM_BASE_DEFAULT + componentInstance.getSourceModelName(); - } else { - interfaceType = getInterfaceType(component, interfaceDefinition.getType()); - } - if (componentInstance == null) { - toscaInterfaceDefinition.setType(interfaceType); - } - toscaInterfaceDefinition.setType(interfaceType); - final Map operations = interfaceDefinition.getOperations(); - Map toscaOperationMap = new HashMap<>(); - - String operationArtifactPath; - for (Map.Entry operationEntry : operations.entrySet()) { - ToscaLifecycleOperationDefinition toscaOperation = new ToscaLifecycleOperationDefinition(); - if (isArtifactPresent(operationEntry)) { - operationArtifactPath = OperationArtifactUtil - .createOperationArtifactPath(component, componentInstance, operationEntry.getValue(), - isAssociatedComponent); - toscaOperation.setImplementation(operationArtifactPath); - } - toscaOperation.setDescription(operationEntry.getValue().getDescription()); - fillToscaOperationInputs(operationEntry.getValue(), dataTypes, toscaOperation, isServiceProxyInterface); + handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent, + isServiceProxyInterface, toscaInterfaceDefinitions, interfaceDefinition); + } + return toscaInterfaceDefinitions; + } - toscaOperationMap.put(operationEntry.getValue().getName(), toscaOperation); - } - toscaInterfaceDefinition.setOperations(toscaOperationMap); + public Map getInterfacesMapFromComponentInstance(final Component component, + final ComponentInstance componentInstance, + final Map dataTypes, + final boolean isAssociatedComponent, + final boolean isServiceProxyInterface) { + final Map toscaInterfaceDefinitions = new HashMap<>(); + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + for (final Map.Entry interfaceEntry : componentInstance.getInterfaces().entrySet()) { + final InterfaceDefinition interfaceDefinition = objectMapper + .convertValue(interfaceEntry.getValue(), InterfaceDefinition.class); + handleInterfaceOperations(component, componentInstance, dataTypes, isAssociatedComponent, + isServiceProxyInterface, toscaInterfaceDefinitions, interfaceDefinition); + } + return toscaInterfaceDefinitions; + } - final Map interfaceInputMap = createInterfaceInputMap(interfaceDefinition, dataTypes); - if (!interfaceInputMap.isEmpty()) { - toscaInterfaceDefinition.setInputs(interfaceInputMap); - } + private void handleInterfaceOperations(final Component component, + final ComponentInstance componentInstance, + final Map dataTypes, + final boolean isAssociatedComponent, + final boolean isServiceProxyInterface, + final Map toscaInterfaceDefinitions, + final InterfaceDefinition interfaceDefinition) { + final String interfaceType; + if (componentInstance != null && LOCAL_INTERFACE_TYPE.equals(interfaceDefinition.getType())) { + interfaceType = DERIVED_FROM_BASE_DEFAULT + componentInstance.getSourceModelName(); + } else { + interfaceType = getInterfaceType(component, interfaceDefinition.getType()); + } + final ToscaInterfaceDefinition toscaInterfaceDefinition = new ToscaInterfaceDefinition(); + if (componentInstance == null) { + toscaInterfaceDefinition.setType(interfaceType); + } + final Map operations = interfaceDefinition.getOperations(); + final Map toscaOperationMap = new HashMap<>(); + + for (final Entry operationEntry : operations.entrySet()) { + final ToscaLifecycleOperationDefinition toscaLifecycleOperationDefinition = + new ToscaLifecycleOperationDefinition(); + handleInterfaceOperationImplementation(component, componentInstance, isAssociatedComponent, + operationEntry, + toscaLifecycleOperationDefinition); + toscaLifecycleOperationDefinition.setDescription(operationEntry.getValue().getDescription()); + fillToscaOperationInputs(operationEntry.getValue(), dataTypes, toscaLifecycleOperationDefinition, + isServiceProxyInterface); + toscaOperationMap.put(operationEntry.getValue().getName(), toscaLifecycleOperationDefinition); + } - Map interfaceDefAsMap = getObjectAsMap(toscaInterfaceDefinition); - if (interfaceDefAsMap.containsKey(INPUTS.getElementName())) { - handleDefaults((Map) interfaceDefAsMap.get(INPUTS.getElementName())); - } - Map operationsMap = (Map) interfaceDefAsMap.remove(OPERATIONS.getElementName()); - if (isServiceProxyInterface) { - //Remove input type and copy default value directly into the proxy node template from the node type - handleServiceProxyOperationInputValue(operationsMap, interfaceType); - } else { - handleDefaults(operationsMap); - } - interfaceDefAsMap.putAll(operationsMap); - toscaInterfaceDefinitions.put(getLastPartOfName(interfaceType), interfaceDefAsMap); + toscaInterfaceDefinition.setOperations(toscaOperationMap); + final Map interfaceInputMap = createInterfaceInputMap(interfaceDefinition, dataTypes); + if (!interfaceInputMap.isEmpty()) { + toscaInterfaceDefinition.setInputs(interfaceInputMap); + } + final Map interfaceDefinitionAsMap = getObjectAsMap(toscaInterfaceDefinition); + if (interfaceDefinitionAsMap.containsKey(INPUTS.getElementName())) { + handleDefaults((Map) interfaceDefinitionAsMap.get(INPUTS.getElementName())); } + final Map operationsMap = + (Map) interfaceDefinitionAsMap.remove(OPERATIONS.getElementName()); - return toscaInterfaceDefinitions; + handleOperationInputValue(operationsMap, interfaceType); + + interfaceDefinitionAsMap.putAll(operationsMap); + toscaInterfaceDefinitions.put(getLastPartOfName(interfaceType), interfaceDefinitionAsMap); + } + + private void handleInterfaceOperationImplementation(final Component component, + final ComponentInstance componentInstance, + final boolean isAssociatedComponent, + final Entry operationEntry, + final ToscaLifecycleOperationDefinition toscaOperation) { + final String operationArtifactPath; + if (isArtifactPresent(operationEntry) && StringUtils + .isNotEmpty(operationEntry.getValue().getImplementation().getArtifactName())) { + operationArtifactPath = OperationArtifactUtil + .createOperationArtifactPath(component, componentInstance, operationEntry.getValue(), + isAssociatedComponent); + toscaOperation.setImplementation(operationArtifactPath); + } else { + toscaOperation.setImplementation(operationEntry.getValue().getImplementation().getArtifactName()); + } } public void removeInterfacesWithoutOperations(final Map interfaceMap) { @@ -244,21 +283,6 @@ public class InterfacesOperationsConverter { return toscaInterfaceInputMap; } - private static void handleServiceProxyOperationInputValue(Map operationsMap, String parentKey) { - for (Map.Entry operationEntry : operationsMap.entrySet()) { - final Object value = operationEntry.getValue(); - final String key = operationEntry.getKey(); - if (value instanceof Map) { - if ("inputs".equals(parentKey)) { - Object defaultValue = getDefaultValue((Map) value); - operationsMap.put(key, defaultValue); - } else { - handleServiceProxyOperationInputValue((Map) value, key); - } - } - } - } - private static Object getDefaultValue(Map inputValueMap) { Object defaultValue = null; for (Map.Entry operationEntry : inputValueMap.entrySet()) { @@ -274,6 +298,22 @@ public class InterfacesOperationsConverter { return defaultValue; } + //Remove input type and copy default value directly into the proxy node template from the node type + private static void handleOperationInputValue(Map operationsMap, String parentKey) { + for (Map.Entry operationEntry : operationsMap.entrySet()) { + final Object value = operationEntry.getValue(); + final String key = operationEntry.getKey(); + if (value instanceof Map) { + if (INPUTS.getElementName().equals(parentKey)) { + Object defaultValue = getDefaultValue((Map) value); + operationsMap.put(key, defaultValue); + } else { + handleOperationInputValue((Map) value, key); + } + } + } + } + /* * workaround for : currently "defaultp" is not being converted to "default" by the relevant code in * ToscaExportHandler so, any string Map key named "defaultp" will have its named changed to "default" diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index f9125648fd..b4bf4e8d42 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -293,7 +293,7 @@ public class ToscaExportHandler { if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) { toscaNode.setNode_types(nodeTypesMap); } - + createServiceSubstitutionNodeTypes(componentCache, component, toscaNode); Either, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component); @@ -486,7 +486,7 @@ public class ToscaExportHandler { toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(),service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType()); if (!isInstance) { // DE268546 - toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(),service.isEcompGeneratedNaming().toString()); + toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(),service.isEcompGeneratedNaming().toString()); toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(),service.isEcompGeneratedNaming().toString()); toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(),service.getNamingPolicy()); } @@ -494,7 +494,7 @@ public class ToscaExportHandler { default: log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType()); } - + for (final String key: component.getCategorySpecificMetadata().keySet()) { toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key)); } @@ -904,6 +904,7 @@ public class ToscaExportHandler { addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props); } + //M3[00001] - NODE TEMPLATE INTERFACES - START handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component); @@ -963,29 +964,22 @@ public class ToscaExportHandler { String instanceUniqueId, Component parentComponent) { - final Map interfaceMap; - // we need to handle service proxy interfaces - if (isComponentOfTypeServiceProxy(componentInstance)) { - if (MapUtils.isEmpty(componentInstanceInterfaces) - || !componentInstanceInterfaces.containsKey(instanceUniqueId)) { - nodeTemplate.setInterfaces(null); - return; - } + if (MapUtils.isEmpty(componentInstanceInterfaces) + || !componentInstanceInterfaces.containsKey(instanceUniqueId)) { + nodeTemplate.setInterfaces(null); + return; + } - final List currServiceInterfaces = - componentInstanceInterfaces.get(instanceUniqueId); + final List currServiceInterfaces = + componentInstanceInterfaces.get(instanceUniqueId); - final Map tmpInterfaces = new HashMap<>(); - currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface - .getUniqueId(), instInterface)); + final Map tmpInterfaces = new HashMap<>(); + currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface + .getUniqueId(), instInterface)); + + final Map interfaceMap = interfacesOperationsConverter + .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance), isComponentOfTypeServiceProxy(componentInstance)); - interfaceMap = interfacesOperationsConverter - .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, true, true); - } else { - interfaceMap = - getComponentInstanceInterfaceInstances(componentInstanceInterfaces, - componentInstance, instanceUniqueId); - } interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap); nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap); } @@ -1210,7 +1204,7 @@ public class ToscaExportHandler { return Either.left(nodeTypesMap); } - + private void createServiceSubstitutionNodeTypes(final Map componentCache, final Component container, final ToscaTemplate toscaNode) { final List componentInstances = container.getComponentInstances(); @@ -1226,11 +1220,11 @@ public class ToscaExportHandler { final Map nodeTypes = toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types(); convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode, nodeTypes, true); } - } + } } private ToscaNodeType createProxyNodeType(Map componentCache, Component origComponent, - Component proxyComponent, ComponentInstance instance) { + Component proxyComponent, ComponentInstance componentInstance) { ToscaNodeType toscaNodeType = new ToscaNodeType(); String derivedFrom = ((Resource) origComponent).getToscaResourceName(); @@ -1241,25 +1235,32 @@ public class ToscaExportHandler { } Map dataTypes = dataTypesEither.left().value(); Map capabilities = this.capabilityRequirementConverter - .convertProxyCapabilities(componentCache, instance, dataTypes); + .convertProxyCapabilities(componentCache, componentInstance, dataTypes); if (MapUtils.isNotEmpty(capabilities)) { toscaNodeType.setCapabilities(capabilities); } List> proxyNodeTypeRequirements = this.capabilityRequirementConverter - .convertProxyRequirements(componentCache, instance); + .convertProxyRequirements(componentCache, componentInstance); if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) { toscaNodeType.setRequirements(proxyNodeTypeRequirements); } Optional> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes); proxyProperties.ifPresent(toscaNodeType::setProperties); - Optional> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes); - if (proxyInterfaces.isPresent()) { - final Map interfaceMap = proxyInterfaces.get(); - interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap); - toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap); + Map interfaceMap = new HashMap<>(); + if (MapUtils.isEmpty(componentInstance.getInterfaces())) { + final Optional> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes); + if (proxyInterfaces.isPresent()) { + interfaceMap = proxyInterfaces.get(); + } + } else { + interfaceMap = interfacesOperationsConverter + .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false); + } + interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap); + toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap); return toscaNodeType; } 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 336b8ec940..18dc67f752 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 @@ -69,6 +69,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade import org.openecomp.sdc.be.model.operations.impl.CapabilityTypeOperation; import org.openecomp.sdc.be.model.tosca.constraints.GreaterOrEqualConstraint; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.tosca.utils.InterfaceTypesNameUtil; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.common.api.ConfigurationSource; @@ -203,7 +204,7 @@ public class ResourceImportManagerTest { testSetRequirments(createResource.left); } - + @Test public void testResourceCreationWithInterfaceImplementation() throws IOException { UploadResourceInfo resourceMD = createDummyResourceMD(); @@ -214,7 +215,7 @@ public class ResourceImportManagerTest { setResourceBusinessLogicMock(); String jsonContent = ImportUtilsTest.loadCustomTypeFileNameToJsonString("custom-types-node-type-with-interface-impl.yml"); - + Map interfaceTypes = new HashMap<>(); final InterfaceDefinition interfaceDefinition = new InterfaceDefinition(); interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard"); @@ -228,7 +229,7 @@ public class ResourceImportManagerTest { .importNormativeResource(jsonContent, resourceMD, user, true, true); assertSetInterfaceImplementation(createResource.left); } - + @Test public void testResourceCreationWithInterfaceImplementation_UnknownInterface() throws IOException { UploadResourceInfo resourceMD = createDummyResourceMD(); @@ -239,7 +240,7 @@ public class ResourceImportManagerTest { setResourceBusinessLogicMock(); String jsonContent = ImportUtilsTest.loadCustomTypeFileNameToJsonString("custom-types-node-type-with-unknown-interface-impl.yml"); - + Map interfaceTypes = new HashMap<>(); final InterfaceDefinition interfaceDefinition = new InterfaceDefinition(); interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard"); @@ -252,7 +253,7 @@ public class ResourceImportManagerTest { ImmutablePair createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true); assertNull(createResource.left.getInterfaces()); } - + @Test public void testResourceCreationWitInterfaceImplementation_UnknownOperation() throws IOException { UploadResourceInfo resourceMD = createDummyResourceMD(); @@ -263,7 +264,7 @@ public class ResourceImportManagerTest { setResourceBusinessLogicMock(); String jsonContent = ImportUtilsTest.loadCustomTypeFileNameToJsonString("custom-types-node-type-with-interface-impl-unknown-operation.yml"); - + Map interfaceTypes = new HashMap<>(); final InterfaceDefinition interfaceDefinition = new InterfaceDefinition(); interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard"); @@ -399,20 +400,16 @@ public class ResourceImportManagerTest { assertEquals("binding", requirement.getName()); } - + private void assertSetInterfaceImplementation(final Resource resource) { final Map interfaces = resource.getInterfaces(); + assertNotNull(interfaces); assertEquals(1, interfaces.size()); - assertTrue(interfaces.containsKey("Standard")); - final InterfaceDefinition interfaceDefinition = interfaces.get("Standard"); - assertEquals("tosca.interfaces.node.lifecycle.Standard", interfaceDefinition.getType()); - assertEquals("tosca.interfaces.node.lifecycle.standard", interfaceDefinition.getUniqueId()); - final Map operations = interfaceDefinition.getOperations(); - assertEquals(1, operations.size()); - - final OperationDataDefinition operation = operations.get("configure"); - assertEquals("'camunda/vnfConfigure'", operation.getImplementation().getArtifactName()); + assertTrue(interfaces.containsKey(InterfaceTypesNameUtil.buildShortName(interfaceDefinition.getType()))); + Map operations = interfaceDefinition.getOperations(); + operations.values().forEach(operationDataDefinition -> + assertTrue(operations.containsKey(operationDataDefinition.getName()))); } private void testSetDerivedFrom(Resource resource) { diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogicTest.java new file mode 100644 index 0000000000..0fd61845e6 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogicTest.java @@ -0,0 +1,173 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import fj.data.Either; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; +import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; +import org.openecomp.sdc.be.components.validation.ComponentValidations; +import org.openecomp.sdc.be.components.validation.UserValidations; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; +import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao; +import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInterface; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.InterfaceDefinition; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.GraphLockOperation; +import org.openecomp.sdc.common.datastructure.Wrapper; + +@ExtendWith(MockitoExtension.class) +public class ComponentInterfaceOperationBusinessLogicTest extends BaseBusinessLogicMock { + + @InjectMocks + private ComponentInterfaceOperationBusinessLogic componentInterfaceOperationBusinessLogic; + + @Mock + private ToscaOperationFacade toscaOperationFacade; + @Mock + private GraphLockOperation graphLockOperation; + @Mock + private JanusGraphDao janusGraphDao; + @Mock + private JanusGraphGenericDao janusGraphGenericDao; + @Mock + private ComponentsUtils componentsUtils; + @Mock + private UserValidations userValidations; + @Mock + private ComponentValidations componentValidations; + + private Component component; + private ComponentInstance componentInstance; + private ComponentParametersView componentFilter; + + @BeforeEach + public void init() { + MockitoAnnotations.initMocks(this); + componentInterfaceOperationBusinessLogic = + new ComponentInterfaceOperationBusinessLogic(elementDao, groupOperation, groupInstanceOperation, + groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation, + componentValidations); + componentInterfaceOperationBusinessLogic.setToscaOperationFacade(toscaOperationFacade); + componentInterfaceOperationBusinessLogic.setGraphLockOperation(graphLockOperation); + componentInterfaceOperationBusinessLogic.setComponentsUtils(componentsUtils); + componentInterfaceOperationBusinessLogic.setUserValidations(userValidations); + componentInterfaceOperationBusinessLogic.setJanusGraphGenericDao(janusGraphGenericDao); + componentInterfaceOperationBusinessLogic.setJanusGraphDao(janusGraphDao); + + initComponentData(); + } + + @Test + public void updateSubstitutionFilterTest() throws BusinessLogicException { + final String componentId = component.getUniqueId(); + final String componentInstanceId = componentInstance.getUniqueId(); + final InterfaceDefinition interfaceDefinition = new InterfaceDefinition(); + interfaceDefinition.setUniqueId(UUID.randomUUID().toString()); + interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard"); + final Map operations = new HashMap<>(); + final OperationDataDefinition operationDataDefinition = new OperationDataDefinition(); + operationDataDefinition.setUniqueId(UUID.randomUUID().toString()); + final ArtifactDataDefinition artifactDataDefinition = new ArtifactDataDefinition(); + artifactDataDefinition.setArtifactName("EO Implementation info"); + operationDataDefinition.setImplementation(artifactDataDefinition); + operations.put("configure", operationDataDefinition); + interfaceDefinition.setOperations(operations ); + + final ComponentInstanceInterface componentInstanceInterface = + new ComponentInstanceInterface("interfaceId", interfaceDefinition); + Map> componentInstancesInterfacesMap = new HashMap<>(); + componentInstancesInterfacesMap.put(componentInstanceId, Collections.singletonList(componentInstanceInterface)); + component.setComponentInstancesInterfaces(componentInstancesInterfacesMap); + componentInstance.setInterfaces( + (Map) new HashMap<>().put(componentInstanceId, interfaceDefinition)); + component.setComponentInstances(Collections.singletonList(componentInstance)); + + when(toscaOperationFacade.getToscaElement(componentId)).thenReturn(Either.left(component)); + when(componentValidations.getComponentInstance(component, componentInstanceId)) + .thenReturn(Optional.of(componentInstance)); + when(graphLockOperation.lockComponent(componentId, NodeTypeEnum.Service)) + .thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacade.updateComponentInstanceInterfaces(component, componentInstanceId)) + .thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacade + .updateComponentInstanceMetadataOfTopologyTemplate(any(Service.class), any(ComponentParametersView.class))) + .thenReturn(Either.left(component)); + when(janusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK); + when(graphLockOperation.unlockComponent(componentId, NodeTypeEnum.Service)) + .thenReturn(StorageOperationStatus.OK); + + final Optional result = componentInterfaceOperationBusinessLogic + .updateComponentInstanceInterfaceOperation(componentId, componentInstanceId, interfaceDefinition, + ComponentTypeEnum.SERVICE, new Wrapper<>(), true); + assertThat(result).isPresent(); + } + + public void initComponentData() { + try { + component = new Service(); + component.setName("MyTestService"); + component.setUniqueId("dac65869-dfb4-40d2-aa20-084324659ec1"); + + componentInstance = new ComponentInstance(); + componentInstance.setUniqueId("dac65869-dfb4-40d2-aa20-084324659ec1.resource0"); + componentInstance.setOriginType(OriginTypeEnum.VFC); + componentInstance.setName("My VFC Instance"); + + componentFilter = new ComponentParametersView(); + componentFilter.disableAll(); + componentFilter.setIgnoreUsers(false); + componentFilter.setIgnoreComponentInstances(false); + componentFilter.setIgnoreInterfaces(false); + componentFilter.setIgnoreComponentInstancesInterfaces(false); + + } catch (final Exception e) { + fail(e.getMessage()); + } + } +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogicTest.java index c83f73b269..548ef1ace9 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogicTest.java @@ -777,8 +777,8 @@ public class InputsBusinessLogicTest { inputDef.setDefaultValue(NEW_VALUE); // update value inputDef.setRequired(Boolean.TRUE); // update value Map newMetadata = new HashMap<>(); - newMetadata.put("key1", "value2"); - newMetadata.put("key2", "value3"); + newMetadata.put("key2", "value2"); + newMetadata.put("key3", "value3"); inputDef.setMetadata(newMetadata); newInputDefs.add(inputDef); @@ -802,8 +802,8 @@ public class InputsBusinessLogicTest { assertEquals(NEW_VALUE, service.getInputs().get(0).getDefaultValue()); assertEquals(Boolean.TRUE, service.getInputs().get(0).isRequired()); assertEquals(2, service.getInputs().get(0).getMetadata().size()); - assertEquals("value2", service.getInputs().get(0).getMetadata().get("key1")); - assertEquals("value3", service.getInputs().get(0).getMetadata().get("key2")); + assertEquals("value2", service.getInputs().get(0).getMetadata().get("key2")); + assertEquals("value3", service.getInputs().get(0).getMetadata().get("key3")); } } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java index 4f569f91cd..d4fb60e878 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverterTest.java @@ -57,6 +57,8 @@ import org.apache.commons.collections4.MapUtils; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; import org.onap.sdc.tosca.services.YamlUtil; import org.openecomp.sdc.be.DummyConfigurationManager; import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; @@ -585,9 +587,6 @@ class InterfacesOperationsConverterTest { for (Map.Entry inputEntry : inputs.entrySet()) { String[] inputNameSplit = inputEntry.getKey().split("_"); Map inputValueObject = (Map) inputEntry.getValue(); - assertEquals(inputNameSplit[1], inputValueObject.get("type")); - Boolean expectedIsRequired = Integer.parseInt(inputNameSplit[2]) % 2 == 0; - assertEquals(expectedIsRequired, inputValueObject.get("required")); validateOperationInputDefinitionDefaultValue(interfaceType, operationName, inputNameSplit[1], Integer.parseInt(inputNameSplit[2]), inputValueObject); } @@ -597,15 +596,16 @@ class InterfacesOperationsConverterTest { private void validateOperationInputDefinitionDefaultValue(String interfaceType, String operationName, String inputType, int index, Map inputValueObject) { - Map mappedInputValue = (Map) inputValueObject.get("default"); - if(mappedInputValue.containsKey(ToscaFunctions.GET_PROPERTY.getFunctionName())) { + if (inputValueObject.containsKey(ToscaFunctions.GET_PROPERTY.getFunctionName())) { String mappedPropertyValue = MAPPED_PROPERTY_NAME + index; - List mappedPropertyDefaultValue = (List) mappedInputValue.get(ToscaFunctions.GET_PROPERTY.getFunctionName()); + List mappedPropertyDefaultValue = (List) inputValueObject + .get(ToscaFunctions.GET_PROPERTY.getFunctionName()); assertEquals(2, mappedPropertyDefaultValue.size()); assertTrue(mappedPropertyDefaultValue.contains(SELF)); assertTrue(mappedPropertyDefaultValue.contains(mappedPropertyValue)); - } else if(mappedInputValue.containsKey(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) { - List mappedPropertyDefaultValue = (List) mappedInputValue.get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName()); + } else if (inputValueObject.containsKey(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) { + List mappedPropertyDefaultValue = (List) inputValueObject + .get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName()); assertEquals(4, mappedPropertyDefaultValue.size()); String mappedPropertyValue = OUTPUT_NAME_PREFIX + inputType + "_" + index; assertTrue(mappedPropertyDefaultValue.contains(SELF)); -- cgit 1.2.3-korg