aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-be/src/main
diff options
context:
space:
mode:
authoraribeiro <anderson.ribeiro@est.tech>2020-11-19 13:28:43 +0000
committerChristophe Closset <christophe.closset@intl.att.com>2021-01-29 08:22:04 +0000
commit5c1f5756bcb5856e2d8b35e3c6ac206f891f8695 (patch)
tree29a7c4424b3ced8800e5bcacc629c8fff8dd8753 /catalog-be/src/main
parent3c957597725f306b4ca06cebfa54fbf0f2622938 (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/main')
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java24
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInterfaceOperationBusinessLogic.java221
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceDefinitionHandler.java9
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java3
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInterfaceOperationServlet.java179
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/InterfacesOperationsConverter.java166
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java67
7 files changed, 561 insertions, 108 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;
}