2d6a619cc7631f46c5e1b2b1148f75e9ca34e9f0
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / OutputsBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2021, Nordix Foundation. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.be.components.impl;
21
22 import fj.data.Either;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Optional;
27 import org.openecomp.sdc.be.components.attribute.AttributeDeclarationOrchestrator;
28 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
29 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
30 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
31 import org.openecomp.sdc.be.components.validation.ComponentValidations;
32 import org.openecomp.sdc.be.dao.api.ActionStatus;
33 import org.openecomp.sdc.be.dao.utils.MapUtil;
34 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
35 import org.openecomp.sdc.be.model.Component;
36 import org.openecomp.sdc.be.model.ComponentInstOutputsMap;
37 import org.openecomp.sdc.be.model.ComponentInstanceOutput;
38 import org.openecomp.sdc.be.model.ComponentParametersView;
39 import org.openecomp.sdc.be.model.OutputDefinition;
40 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
41 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
42 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
43 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
44 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
45 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
46 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
47 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
48 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
49 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
50 import org.openecomp.sdc.common.log.enums.StatusCode;
51 import org.openecomp.sdc.common.log.wrappers.Logger;
52 import org.openecomp.sdc.exception.ResponseFormat;
53 import org.springframework.beans.factory.annotation.Autowired;
54
55 @org.springframework.stereotype.Component("outputsBusinessLogic")
56 public class OutputsBusinessLogic extends BaseBusinessLogic {
57
58     private static final String CREATE_OUTPUT = "CreateOutput";
59     private static final Logger log = Logger.getLogger(OutputsBusinessLogic.class);
60     private static final String FAILED_TO_FOUND_COMPONENT_ERROR = "Failed to found component {}, error: {}";
61     private static final String GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP = "Going to execute rollback on create group.";
62     private static final String GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP = "Going to execute commit on create group.";
63     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(OutputsBusinessLogic.class);
64     private static final String FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_COMPONENT_INSTANCE_ID = "Failed to found component instance outputs componentInstanceId: {}";
65     private static final String FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_ERROR = "Failed to found component instance outputs {}, error: {}";
66     private final AttributeDeclarationOrchestrator attributeDeclarationOrchestrator;
67
68     @Autowired
69     public OutputsBusinessLogic(final IElementOperation elementDao, final IGroupOperation groupOperation,
70                                 final IGroupInstanceOperation groupInstanceOperation, final IGroupTypeOperation groupTypeOperation,
71                                 final InterfaceOperation interfaceOperation, final InterfaceLifecycleOperation interfaceLifecycleTypeOperation,
72                                 final AttributeDeclarationOrchestrator attributeDeclarationOrchestrator,
73                                 final ArtifactsOperations artifactToscaOperation) {
74         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, interfaceLifecycleTypeOperation,
75             artifactToscaOperation);
76         this.attributeDeclarationOrchestrator = attributeDeclarationOrchestrator;
77     }
78
79     public Either<List<ComponentInstanceOutput>, ResponseFormat> getComponentInstanceOutputs(final String userId, final String componentId,
80                                                                                              final String componentInstanceId) {
81         validateUserExists(userId);
82         final ComponentParametersView filters = new ComponentParametersView();
83         filters.disableAll();
84         filters.setIgnoreOutputs(false);
85         filters.setIgnoreComponentInstances(false);
86         filters.setIgnoreComponentInstancesOutputs(false);
87         final Either<Component, StorageOperationStatus> getComponentEither = toscaOperationFacade.getToscaElement(componentId, filters);
88         if (getComponentEither.isRight()) {
89             ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentEither.right().value());
90             log.debug(FAILED_TO_FOUND_COMPONENT_ERROR, componentId, actionStatus);
91             return Either.right(componentsUtils.getResponseFormat(actionStatus));
92         }
93         final Component component = getComponentEither.left().value();
94         if (!ComponentValidations.validateComponentInstanceExist(component, componentInstanceId)) {
95             final ActionStatus actionStatus = ActionStatus.COMPONENT_INSTANCE_NOT_FOUND;
96             log.debug(FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_ERROR, componentInstanceId, actionStatus);
97             loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, component.getComponentMetadataForSupportLog(), StatusCode.ERROR,
98                 FAILED_TO_FOUND_COMPONENT_INSTANCE_OUTPUTS_COMPONENT_INSTANCE_ID, componentInstanceId);
99             return Either.right(componentsUtils.getResponseFormat(actionStatus));
100         }
101         final Map<String, List<ComponentInstanceOutput>> ciOutputs = Optional.ofNullable(component.getComponentInstancesOutputs())
102             .orElse(Collections.emptyMap());
103         return Either.left(ciOutputs.getOrDefault(componentInstanceId, Collections.emptyList()));
104     }
105
106     @Override
107     public Either<List<OutputDefinition>, ResponseFormat> declareAttributes(final String userId, final String componentId,
108                                                                             final ComponentTypeEnum componentTypeEnum,
109                                                                             final ComponentInstOutputsMap componentInstOutputsMap) {
110         return createMultipleOutputs(userId, componentId, componentTypeEnum, componentInstOutputsMap, true, false);
111     }
112
113     public Either<List<OutputDefinition>, ResponseFormat> createMultipleOutputs(final String userId, final String componentId,
114                                                                                 final ComponentTypeEnum componentType,
115                                                                                 final ComponentInstOutputsMap componentInstOutputsMapUi,
116                                                                                 final boolean shouldLockComp, final boolean inTransaction) {
117         Either<List<OutputDefinition>, ResponseFormat> result = null;
118         org.openecomp.sdc.be.model.Component component = null;
119         try {
120             validateUserExists(userId);
121             component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
122             result = attributeDeclarationOrchestrator.declareAttributesToOutputs(component, componentInstOutputsMapUi).left()
123                 .bind(outputsToCreate -> prepareOutputsForCreation(userId, componentId, outputsToCreate)).right()
124                 .map(componentsUtils::getResponseFormat);
125             return result;
126         } catch (final ByResponseFormatComponentException e) {
127             log.error("#createMultipleOutputs: Exception thrown: ", e);
128             result = Either.right(e.getResponseFormat());
129             return result;
130         } finally {
131             if (!inTransaction) {
132                 if (result == null || result.isRight()) {
133                     log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
134                     janusGraphDao.rollback();
135                 } else {
136                     log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
137                     janusGraphDao.commit();
138                 }
139             }
140             // unlock resource
141             if (shouldLockComp && component != null) {
142                 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
143             }
144         }
145     }
146
147     private org.openecomp.sdc.be.model.Component getAndValidateComponentForCreate(final String userId, final String componentId,
148                                                                                   final ComponentTypeEnum componentType,
149                                                                                   final boolean shouldLockComp) {
150         final ComponentParametersView componentParametersView = getBaseComponentParametersView();
151         final org.openecomp.sdc.be.model.Component component = validateComponentExists(componentId, componentType, componentParametersView);
152         if (shouldLockComp) {
153             // lock the component
154             lockComponent(component, CREATE_OUTPUT);
155         }
156         validateCanWorkOnComponent(component, userId);
157         return component;
158     }
159
160     private Either<List<OutputDefinition>, StorageOperationStatus> prepareOutputsForCreation(final String userId, final String cmptId,
161                                                                                              final List<OutputDefinition> outputsToCreate) {
162         final Map<String, OutputDefinition> outputsToPersist = MapUtil.toMap(outputsToCreate, OutputDefinition::getName);
163         assignOwnerIdToOutputs(userId, outputsToPersist);
164         return toscaOperationFacade.addOutputsToComponent(outputsToPersist, cmptId).left().map(persistedOutputs -> outputsToCreate);
165     }
166
167     private void assignOwnerIdToOutputs(final String userId, final Map<String, OutputDefinition> outputsToCreate) {
168         outputsToCreate.values().forEach(outputDefinition -> outputDefinition.setOwnerId(userId));
169     }
170
171     private ComponentParametersView getBaseComponentParametersView() {
172         final ComponentParametersView componentParametersView = new ComponentParametersView();
173         componentParametersView.disableAll();
174         componentParametersView.setIgnoreOutputs(false);
175         componentParametersView.setIgnoreAttributes(false);
176         componentParametersView.setIgnoreComponentInstances(false);
177         componentParametersView.setIgnoreComponentInstancesOutputs(false);
178         componentParametersView.setIgnoreComponentInstancesAttributes(false);
179         componentParametersView.setIgnoreUsers(false);
180         return componentParametersView;
181     }
182
183     /**
184      * Delete output from component
185      *
186      * @param componentId
187      * @param userId
188      * @param outputId
189      * @return
190      */
191     public OutputDefinition deleteOutput(final String componentId, final String userId, final String outputId) {
192         Either<OutputDefinition, ResponseFormat> deleteEither = null;
193         if (log.isDebugEnabled()) {
194             log.debug("Going to delete output id: {}", outputId);
195         }
196         validateUserExists(userId);
197         final ComponentParametersView componentParametersView = getBaseComponentParametersView();
198         componentParametersView.setIgnoreAttributes(false);
199         final Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentEither = toscaOperationFacade
200             .getToscaElement(componentId, componentParametersView);
201         if (componentEither.isRight()) {
202             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(componentEither.right().value()));
203         }
204         final org.openecomp.sdc.be.model.Component component = componentEither.left().value();
205         // Validate outputId is child of the component
206         final Optional<OutputDefinition> optionalOutput = component.getOutputs().stream().
207             // filter by ID
208                 filter(output -> output.getUniqueId().equals(outputId)).
209             // Get the output
210                 findAny();
211         if (!optionalOutput.isPresent()) {
212             throw new ByActionStatusComponentException(ActionStatus.OUTPUT_IS_NOT_CHILD_OF_COMPONENT, outputId, componentId);
213         }
214         final OutputDefinition outputForDelete = optionalOutput.get();
215         // Lock component
216         lockComponent(componentId, component, "deleteOutput");
217         // Delete output operations
218         boolean failed = false;
219         try {
220             final StorageOperationStatus status = toscaOperationFacade.deleteOutputOfResource(component, outputForDelete.getName());
221             if (status != StorageOperationStatus.OK) {
222                 log.debug("Component id: {} delete output id: {} failed", componentId, outputId);
223                 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status), component.getName());
224             }
225             final StorageOperationStatus storageOperationStatus = attributeDeclarationOrchestrator
226                 .unDeclareAttributesAsOutputs(component, outputForDelete);
227             if (storageOperationStatus != StorageOperationStatus.OK) {
228                 log.debug("Component id: {} update attributes declared as output for outputId: {} failed", componentId, outputId);
229                 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(storageOperationStatus), component.getName());
230             }
231             return outputForDelete;
232         } catch (final ComponentException e) {
233             failed = true;
234             throw e;
235         } finally {
236             unlockComponent(failed, component);
237         }
238     }
239 }