diff options
author | aribeiro <anderson.ribeiro@est.tech> | 2020-11-19 13:28:43 +0000 |
---|---|---|
committer | Christophe Closset <christophe.closset@intl.att.com> | 2021-01-29 08:22:04 +0000 |
commit | 5c1f5756bcb5856e2d8b35e3c6ac206f891f8695 (patch) | |
tree | 29a7c4424b3ced8800e5bcacc629c8fff8dd8753 /catalog-be/src | |
parent | 3c957597725f306b4ca06cebfa54fbf0f2622938 (diff) |
Add support for updating interface operations
Allows to update interface operations on a component instance.
Issue-ID: SDC-3446
Signed-off-by: aribeiro <anderson.ribeiro@est.tech>
Signed-off-by: andre.schmid <andre.schmid@est.tech>
Change-Id: I6a2c44997c04d9d9ea298e3d0bc971da7b137799
Diffstat (limited to 'catalog-be/src')
11 files changed, 759 insertions, 136 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 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<String, InterfaceDefinition> 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<ComponentInstance> updateComponentInstanceInterfaceOperation(final String componentId, + final String componentInstanceId, + final InterfaceDefinition interfaceDefinition, + final ComponentTypeEnum componentTypeEnum, + final Wrapper<ResponseFormat> errorWrapper, + final boolean shouldLock) + throws BusinessLogicException { + + final Component component = getComponent(componentId); + final Optional<ComponentInstance> 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<String, List<ComponentInstanceInterface>> componentInstancesInterfaceMap = component + .getComponentInstancesInterfaces(); + if (MapUtils.isEmpty(componentInstancesInterfaceMap)) { + componentInstancesInterfaceMap = new HashMap<>(); + component.setComponentInstancesInterfaces(componentInstancesInterfaceMap); + } + final List<ComponentInstanceInterface> 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<OperationDataDefinition> 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<ComponentInstanceInterface> 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<Component, StorageOperationStatus> 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<String, Object> 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<String, Object> interfaceInputs = (Map<String, Object>) operationDefinitionMap.get(INPUTS.getElementName()); @@ -189,6 +194,8 @@ public class InterfaceDefinitionHandler { final ListDataDefinition<OperationInputDefinition> inputs = new ListDataDefinition<>(); for (final Entry<String, Object> 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<String, Object> 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<InterfaceDefinition> mappedInterfaceOperationData = getMappedInterfaceData(data, userModifier, componentTypeEnum); + if (mappedInterfaceOperationData.isEmpty()) { + LOGGER.error(INTERFACE_OPERATION_CONTENT_INVALID, data); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + final Wrapper<ResponseFormat> errorWrapper = new Wrapper<>(); + try { + final Optional<ComponentInstance> 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<InterfaceDefinition> getMappedInterfaceData(final String inputJson, + final User user, + final ComponentTypeEnum componentTypeEnum) { + final Either<UiComponentDataTransfer, ResponseFormat> 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<String, DataTypeDefinition> dataTypes, final boolean isAssociatedComponent, final boolean isServiceProxyInterface) { - if(MapUtils.isEmpty(interfaces)) { + if (MapUtils.isEmpty(interfaces)) { return null; } - Map<String, Object> toscaInterfaceDefinitions = new HashMap<>(); + final Map<String, Object> 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<String, OperationDataDefinition> operations = interfaceDefinition.getOperations(); - Map<String, Object> toscaOperationMap = new HashMap<>(); - - String operationArtifactPath; - for (Map.Entry<String, OperationDataDefinition> 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<String, Object> getInterfacesMapFromComponentInstance(final Component component, + final ComponentInstance componentInstance, + final Map<String, DataTypeDefinition> dataTypes, + final boolean isAssociatedComponent, + final boolean isServiceProxyInterface) { + final Map<String, Object> toscaInterfaceDefinitions = new HashMap<>(); + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + for (final Map.Entry<String, Object> 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<String, Object> interfaceInputMap = createInterfaceInputMap(interfaceDefinition, dataTypes); - if (!interfaceInputMap.isEmpty()) { - toscaInterfaceDefinition.setInputs(interfaceInputMap); - } + private void handleInterfaceOperations(final Component component, + final ComponentInstance componentInstance, + final Map<String, DataTypeDefinition> dataTypes, + final boolean isAssociatedComponent, + final boolean isServiceProxyInterface, + final Map<String, Object> 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<String, OperationDataDefinition> operations = interfaceDefinition.getOperations(); + final Map<String, Object> toscaOperationMap = new HashMap<>(); + + for (final Entry<String, OperationDataDefinition> 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<String, Object> interfaceDefAsMap = getObjectAsMap(toscaInterfaceDefinition); - if (interfaceDefAsMap.containsKey(INPUTS.getElementName())) { - handleDefaults((Map<String, Object>) interfaceDefAsMap.get(INPUTS.getElementName())); - } - Map<String, Object> operationsMap = (Map<String, Object>) 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<String, Object> interfaceInputMap = createInterfaceInputMap(interfaceDefinition, dataTypes); + if (!interfaceInputMap.isEmpty()) { + toscaInterfaceDefinition.setInputs(interfaceInputMap); + } + final Map<String, Object> interfaceDefinitionAsMap = getObjectAsMap(toscaInterfaceDefinition); + if (interfaceDefinitionAsMap.containsKey(INPUTS.getElementName())) { + handleDefaults((Map<String, Object>) interfaceDefinitionAsMap.get(INPUTS.getElementName())); } + final Map<String, Object> operationsMap = + (Map<String, Object>) 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<String, OperationDataDefinition> 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<String, Object> interfaceMap) { @@ -244,21 +283,6 @@ public class InterfacesOperationsConverter { return toscaInterfaceInputMap; } - private static void handleServiceProxyOperationInputValue(Map<String, Object> operationsMap, String parentKey) { - for (Map.Entry<String, Object> 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<String, Object>) value); - operationsMap.put(key, defaultValue); - } else { - handleServiceProxyOperationInputValue((Map<String, Object>) value, key); - } - } - } - } - private static Object getDefaultValue(Map<String, Object> inputValueMap) { Object defaultValue = null; for (Map.Entry<String, Object> 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<String, Object> operationsMap, String parentKey) { + for (Map.Entry<String, Object> 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<String, Object>) value); + operationsMap.put(key, defaultValue); + } else { + handleOperationInputValue((Map<String, Object>) 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<Map<String, Object>, 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<String, Object> 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<ComponentInstanceInterface> currServiceInterfaces = - componentInstanceInterfaces.get(instanceUniqueId); + final List<ComponentInstanceInterface> currServiceInterfaces = + componentInstanceInterfaces.get(instanceUniqueId); - final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>(); - currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface - .getUniqueId(), instInterface)); + final Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>(); + currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface + .getUniqueId(), instInterface)); + + final Map<String, Object> 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<String, Component> componentCache, final Component container, final ToscaTemplate toscaNode) { final List<ComponentInstance> componentInstances = container.getComponentInstances(); @@ -1226,11 +1220,11 @@ public class ToscaExportHandler { final Map<String, ToscaNodeType> nodeTypes = toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types(); convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode, nodeTypes, true); } - } + } } private ToscaNodeType createProxyNodeType(Map<String, Component> 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<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value(); Map<String, ToscaCapability> capabilities = this.capabilityRequirementConverter - .convertProxyCapabilities(componentCache, instance, dataTypes); + .convertProxyCapabilities(componentCache, componentInstance, dataTypes); if (MapUtils.isNotEmpty(capabilities)) { toscaNodeType.setCapabilities(capabilities); } List<Map<String, ToscaRequirement>> proxyNodeTypeRequirements = this.capabilityRequirementConverter - .convertProxyRequirements(componentCache, instance); + .convertProxyRequirements(componentCache, componentInstance); if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) { toscaNodeType.setRequirements(proxyNodeTypeRequirements); } Optional<Map<String, ToscaProperty>> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes); proxyProperties.ifPresent(toscaNodeType::setProperties); - Optional<Map<String, Object>> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes); - if (proxyInterfaces.isPresent()) { - final Map<String, Object> interfaceMap = proxyInterfaces.get(); - interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap); - toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap); + Map<String, Object> interfaceMap = new HashMap<>(); + if (MapUtils.isEmpty(componentInstance.getInterfaces())) { + final Optional<Map<String, Object>> 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<String, InterfaceDefinition> 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<String, InterfaceDefinition> interfaceTypes = new HashMap<>(); final InterfaceDefinition interfaceDefinition = new InterfaceDefinition(); interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard"); @@ -252,7 +253,7 @@ public class ResourceImportManagerTest { ImmutablePair<Resource, ActionStatus> 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<String, InterfaceDefinition> 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<String, InterfaceDefinition> 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<String, OperationDataDefinition> 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<String, OperationDataDefinition> 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<String, OperationDataDefinition> 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<String, List<ComponentInstanceInterface>> componentInstancesInterfacesMap = new HashMap<>(); + componentInstancesInterfacesMap.put(componentInstanceId, Collections.singletonList(componentInstanceInterface)); + component.setComponentInstancesInterfaces(componentInstancesInterfacesMap); + componentInstance.setInterfaces( + (Map<String, Object>) 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<ComponentInstance> 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<String, String> 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<String, Object> inputEntry : inputs.entrySet()) { String[] inputNameSplit = inputEntry.getKey().split("_"); Map<String, Object> inputValueObject = (Map<String, Object>) 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<String, Object> inputValueObject) { - Map<String, Object> mappedInputValue = (Map<String, Object>) inputValueObject.get("default"); - if(mappedInputValue.containsKey(ToscaFunctions.GET_PROPERTY.getFunctionName())) { + if (inputValueObject.containsKey(ToscaFunctions.GET_PROPERTY.getFunctionName())) { String mappedPropertyValue = MAPPED_PROPERTY_NAME + index; - List<String> mappedPropertyDefaultValue = (List<String>) mappedInputValue.get(ToscaFunctions.GET_PROPERTY.getFunctionName()); + List<String> mappedPropertyDefaultValue = (List<String>) 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<String> mappedPropertyDefaultValue = (List<String>) mappedInputValue.get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName()); + } else if (inputValueObject.containsKey(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) { + List<String> mappedPropertyDefaultValue = (List<String>) inputValueObject + .get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName()); assertEquals(4, mappedPropertyDefaultValue.size()); String mappedPropertyValue = OUTPUT_NAME_PREFIX + inputType + "_" + index; assertTrue(mappedPropertyDefaultValue.contains(SELF)); |