Update vulnerable package dependencies
[sdc.git] / openecomp-be / lib / openecomp-healing-lib / openecomp-sdc-healing-impl / src / main / java / org / openecomp / sdc / healing / healers / NetworkPackageHealer.java
1 /*
2  * Copyright © 2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  * ================================================================================
16  * Modifications copyright (c) 2019 Nokia
17  * ================================================================================
18  */
19 package org.openecomp.sdc.healing.healers;
20
21 import static org.openecomp.core.zusammen.api.ZusammenUtil.buildElement;
22 import static org.openecomp.core.zusammen.api.ZusammenUtil.buildStructuralElement;
23 import static org.openecomp.core.zusammen.api.ZusammenUtil.createSessionContext;
24
25 import com.amdocs.zusammen.adaptor.inbound.api.types.item.Element;
26 import com.amdocs.zusammen.adaptor.inbound.api.types.item.ElementInfo;
27 import com.amdocs.zusammen.adaptor.inbound.api.types.item.ZusammenElement;
28 import com.amdocs.zusammen.datatypes.Id;
29 import com.amdocs.zusammen.datatypes.SessionContext;
30 import com.amdocs.zusammen.datatypes.item.Action;
31 import com.amdocs.zusammen.datatypes.item.ElementContext;
32 import com.amdocs.zusammen.utils.fileutils.FileUtils;
33 import java.io.ByteArrayInputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.nio.ByteBuffer;
37 import java.util.Collection;
38 import java.util.Objects;
39 import org.apache.commons.io.IOUtils;
40 import org.apache.commons.lang3.ArrayUtils;
41 import org.apache.commons.lang3.StringUtils;
42 import org.openecomp.core.utilities.file.FileContentHandler;
43 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
44 import org.openecomp.core.zusammen.api.ZusammenAdaptor;
45 import org.openecomp.core.zusammen.api.ZusammenAdaptorFactory;
46 import org.openecomp.sdc.common.errors.CoreException;
47 import org.openecomp.sdc.common.errors.ErrorCode;
48 import org.openecomp.sdc.common.utils.CommonUtil;
49 import org.openecomp.sdc.datatypes.error.ErrorLevel;
50 import org.openecomp.sdc.datatypes.model.ElementType;
51 import org.openecomp.sdc.healing.interfaces.Healer;
52 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
53 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDaoFactory;
54 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OnboardingMethod;
55 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
56 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateEntity;
57 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
58 import org.openecomp.sdc.vendorsoftwareproduct.factory.CandidateServiceFactory;
59 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.CandidateService;
60 import org.openecomp.sdc.vendorsoftwareproduct.services.utils.CandidateEntityBuilder;
61 import org.openecomp.sdc.versioning.dao.types.Version;
62
63 public class NetworkPackageHealer implements Healer {
64
65     private static final byte[] EMPTY_DATA_BYTES = "{}".getBytes();
66     private static final String MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_ERROR = "Vsp with invalid structure: does not contain element OrchestrationTemplateCandidate";
67     private static final String MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_CONTENT_ERROR =
68         "Vsp with invalid structure: does not contain element OrchestrationTemplateCandidateContent" + " under OrchestrationTemplateCandidate";
69     private static final String MISSING_VSP_MODEL_ERROR = "Vsp with invalid structure: does not contain element VspModel";
70     private static final String MISSING_ORCHESTRATION_TEMPLATE_ERROR =
71         "Vsp with invalid structure: does not contain element OrchestrationTemplate" + " under VspModel element";
72     private static final String MISSING_ORCHESTRATION_TEMPLATE_VALIDATE_DATA_ERROR =
73         "Vsp with invalid structure: does not contain element OrchestrationTemplateValidationData" + " under OrchestrationTemplate element";
74     private final VendorSoftwareProductInfoDao vspInfoDao;
75     private final ZusammenAdaptor zusammenAdaptor;
76     private final CandidateEntityBuilder candidateEntityBuilder;
77
78     public NetworkPackageHealer() {
79         this(VendorSoftwareProductInfoDaoFactory.getInstance().createInterface(), ZusammenAdaptorFactory.getInstance().createInterface(),
80             CandidateServiceFactory.getInstance().createInterface());
81     }
82
83     private NetworkPackageHealer(VendorSoftwareProductInfoDao vspInfoDao, ZusammenAdaptor zusammenAdaptor, CandidateService candidateService) {
84         this(vspInfoDao, zusammenAdaptor, new CandidateEntityBuilder(candidateService));
85     }
86
87     NetworkPackageHealer(VendorSoftwareProductInfoDao vspInfoDao, ZusammenAdaptor zusammenAdaptor, CandidateEntityBuilder candidateEntityBuilder) {
88         this.vspInfoDao = vspInfoDao;
89         this.zusammenAdaptor = zusammenAdaptor;
90         this.candidateEntityBuilder = candidateEntityBuilder;
91     }
92
93     @Override
94     public boolean isHealingNeeded(String itemId, Version version) {
95         return OnboardingMethod.NetworkPackage.name().equals(vspInfoDao.get(new VspDetails(itemId, version)).getOnboardingMethod())
96             && isVspMissingAddedElements(itemId, version);
97     }
98
99     @Override
100     public void heal(String itemId, Version version) throws Exception {
101         SessionContext context = createSessionContext();
102         ElementContext elementContext = new ElementContext(itemId, version.getId());
103         Element candidateElement = getElement(context, elementContext, null, ElementType.OrchestrationTemplateCandidate,
104             MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_ERROR);
105         Collection<Element> candidateSubs = zusammenAdaptor.listElementData(context, elementContext, candidateElement.getElementId());
106         Id candidateValidationElementId = creatIfAbsentCandidateValidationElementId(candidateSubs, context, elementContext, candidateElement);
107         Element orchestrationTemplateElement = getOrchestrationTemplateElement(context, elementContext);
108         Collection<Element> orchestrationTemplateSubs = zusammenAdaptor
109             .listElementData(context, elementContext, orchestrationTemplateElement.getElementId());
110         Id structureElementId = createIfAbsentStructureElementId(orchestrationTemplateSubs, context, elementContext, orchestrationTemplateElement);
111         Element orchestrationTemplateValidationElement = getOrchestrationTemplateValidationElement(orchestrationTemplateSubs);
112         OrchestrationTemplateEntity orchestrationTemplateEntity = getOrchestrationTemplateEntity(orchestrationTemplateElement,
113             orchestrationTemplateValidationElement);
114         if (StringUtils.isEmpty(orchestrationTemplateEntity.getFileSuffix())) {
115             return;
116         }
117         Element candidateContentElement = getCandidateContentElement(candidateSubs);
118         VspDetails vspDetails = vspInfoDao.get(new VspDetails(itemId, version));
119         if (isEqual(orchestrationTemplateEntity, getCandidateData(candidateElement, candidateContentElement))) {
120             if (isProcessedEntityValid(orchestrationTemplateEntity)) {
121                 emptyStructureElementAndSub(context, elementContext, candidateElement.getElementId(), ElementType.OrchestrationTemplateCandidate,
122                     candidateContentElement.getElementId(), ElementType.OrchestrationTemplateCandidateContent);
123                 populateOrchestrationTemplateStructure(orchestrationTemplateElement.getData(), structureElementId, vspDetails, context,
124                     elementContext);
125             } else {
126                 emptyStructureElementAndSub(context, elementContext, orchestrationTemplateElement.getElementId(), ElementType.OrchestrationTemplate,
127                     orchestrationTemplateValidationElement.getElementId(), ElementType.OrchestrationTemplateValidationData);
128                 populateCandidateValidationData(context, elementContext, candidateValidationElementId,
129                     orchestrationTemplateEntity.getValidationData());
130             }
131         } else {
132             populateOrchestrationTemplateStructure(orchestrationTemplateElement.getData(), structureElementId, vspDetails, context, elementContext);
133         }
134     }
135
136     private boolean isVspMissingAddedElements(String vspId, Version version) {
137         SessionContext context = createSessionContext();
138         ElementContext elementContext = new ElementContext(vspId, version.getId());
139         return zusammenAdaptor.listElementsByName(context, elementContext, null, ElementType.OrchestrationTemplateCandidate.name()).stream()
140             .noneMatch(candidateSub -> ElementType.OrchestrationTemplateCandidateValidationData.name().equals(candidateSub.getInfo().getName()));
141     }
142
143     private boolean isEqual(OrchestrationTemplateEntity orchestrationTemplateEntity,
144                             OrchestrationTemplateCandidateData orchestrationTemplateCandidateData) {
145         return orchestrationTemplateEntity.getFileName().equals(orchestrationTemplateCandidateData.getFileName()) && orchestrationTemplateEntity
146             .getFileSuffix().equals(orchestrationTemplateCandidateData.getFileSuffix());
147     }
148
149     private boolean isProcessedEntityValid(OrchestrationTemplateEntity orchestrationTemplateEntity) {
150         return !orchestrationTemplateEntity.getValidationData().contains(ErrorLevel.ERROR.name());
151     }
152
153     private void populateCandidateValidationData(SessionContext context, ElementContext elementContext, Id candidateValidationElementId,
154                                                  String validationData) {
155         ZusammenElement candidateValidationElement = buildStructuralElement(ElementType.OrchestrationTemplateCandidateValidationData, Action.UPDATE);
156         candidateValidationElement.setElementId(candidateValidationElementId);
157         candidateValidationElement.setData(new ByteArrayInputStream(validationData.getBytes()));
158         zusammenAdaptor.saveElement(context, elementContext, candidateValidationElement, "Healed Orchestration Template Candidate Validation data");
159     }
160
161     private void populateOrchestrationTemplateStructure(InputStream processedFile, Id structureElementId, VspDetails vspDetails,
162                                                         SessionContext context, ElementContext elementContext) throws Exception {
163         byte[] byteData = FileUtils.toByteArray(processedFile);
164         FileContentHandler contentMap = CommonUtil.validateAndUploadFileContent(OnboardingTypesEnum.ZIP, byteData);
165         OrchestrationTemplateCandidateData orchestrationTemplateEntityData = candidateEntityBuilder
166             .buildCandidateEntityFromZip(vspDetails, byteData, contentMap, null);
167         String fileDataStructure = orchestrationTemplateEntityData.getFilesDataStructure();
168         ZusammenElement orchestrationTemplateStructure = buildStructuralElement(ElementType.OrchestrationTemplateStructure, Action.UPDATE);
169         orchestrationTemplateStructure.setElementId(structureElementId);
170         orchestrationTemplateStructure.setData(new ByteArrayInputStream(fileDataStructure.getBytes()));
171         zusammenAdaptor.saveElement(context, elementContext, orchestrationTemplateStructure, "Healed Orchestration Template Structure");
172     }
173
174     private Element getOrchestrationTemplateElement(SessionContext context, ElementContext elementContext) {
175         ElementInfo vspModelElement = zusammenAdaptor.getElementInfoByName(context, elementContext, null, ElementType.VspModel.name())
176             .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder().withMessage(MISSING_VSP_MODEL_ERROR).build()));
177         return getElement(context, elementContext, vspModelElement.getId(), ElementType.OrchestrationTemplate, MISSING_ORCHESTRATION_TEMPLATE_ERROR);
178     }
179
180     private Element getOrchestrationTemplateValidationElement(Collection<Element> orchestrationTemplateSubs) {
181         return orchestrationTemplateSubs.stream().filter(
182             orchestrationTemplateSub -> ElementType.OrchestrationTemplateValidationData.name().equals(orchestrationTemplateSub.getInfo().getName()))
183             .findFirst().orElseThrow(
184                 () -> new CoreException(new ErrorCode.ErrorCodeBuilder().withMessage(MISSING_ORCHESTRATION_TEMPLATE_VALIDATE_DATA_ERROR).build()));
185     }
186
187     private Element getCandidateContentElement(Collection<Element> candidateSubs) {
188         return candidateSubs.stream()
189             .filter(candidateSub -> ElementType.OrchestrationTemplateCandidateContent.name().equals(candidateSub.getInfo().getName())).findFirst()
190             .orElseThrow(() -> new CoreException(
191                 new ErrorCode.ErrorCodeBuilder().withMessage(MISSING_ORCHESTRATION_TEMPLATE_CANDIDATE_CONTENT_ERROR).build()));
192     }
193
194     private Id createIfAbsentStructureElementId(Collection<Element> orchestrationTemplateSubs, SessionContext context, ElementContext elementContext,
195                                                 Element orchestrationTemplateElement) {
196         return orchestrationTemplateSubs.stream().filter(
197             orchestrationTemplateSub -> ElementType.OrchestrationTemplateStructure.name().equals(orchestrationTemplateSub.getInfo().getName()))
198             .findFirst().map(Element::getElementId).orElse(addStructureSubElement(context, elementContext, ElementType.OrchestrationTemplateStructure,
199                 orchestrationTemplateElement.getElementId()));
200     }
201
202     private Id creatIfAbsentCandidateValidationElementId(Collection<Element> candidateSubs, SessionContext context, ElementContext elementContext,
203                                                          Element candidateElement) {
204         return candidateSubs.stream()
205             .filter(candidateSub -> ElementType.OrchestrationTemplateCandidateValidationData.name().equals(candidateSub.getInfo().getName()))
206             .findFirst().map(Element::getElementId).orElse(
207                 addStructureSubElement(context, elementContext, ElementType.OrchestrationTemplateCandidateValidationData,
208                     candidateElement.getElementId()));
209     }
210
211     private Element getElement(SessionContext context, ElementContext elementContext, Id parentElementId, ElementType elementType,
212                                String errorMessage) {
213         return zusammenAdaptor.getElementByName(context, elementContext, parentElementId, elementType.name())
214             .orElseThrow(() -> new CoreException(new ErrorCode.ErrorCodeBuilder().withMessage(errorMessage).build()));
215     }
216
217     private OrchestrationTemplateEntity getOrchestrationTemplateEntity(Element orchestrationTemplateElement, Element validationDataElement) {
218         OrchestrationTemplateEntity orchestrationTemplateEntity = new OrchestrationTemplateEntity();
219         if (isNotEmpty(orchestrationTemplateElement.getData())) {
220             orchestrationTemplateEntity.setContentData(ByteBuffer.wrap(FileUtils.toByteArray(orchestrationTemplateElement.getData())));
221         }
222         orchestrationTemplateEntity.setFileSuffix(validationDataElement.getInfo().getProperty(InfoPropertyName.FILE_SUFFIX.getVal()));
223         orchestrationTemplateEntity.setFileName(validationDataElement.getInfo().getProperty(InfoPropertyName.FILE_NAME.getVal()));
224         if (isNotEmpty(validationDataElement.getData())) {
225             orchestrationTemplateEntity.setValidationData(new String(FileUtils.toByteArray(validationDataElement.getData())));
226         }
227         return orchestrationTemplateEntity;
228     }
229
230     private OrchestrationTemplateCandidateData getCandidateData(Element candidateElement, Element candidateContentElement) {
231         OrchestrationTemplateCandidateData candidateData = new OrchestrationTemplateCandidateData();
232         candidateData.setFilesDataStructure(new String(FileUtils.toByteArray(candidateElement.getData())));
233         candidateData.setContentData(ByteBuffer.wrap(FileUtils.toByteArray(candidateContentElement.getData())));
234         candidateData.setFileSuffix(candidateContentElement.getInfo().getProperty(InfoPropertyName.FILE_SUFFIX.getVal()));
235         candidateData.setFileName(candidateContentElement.getInfo().getProperty(InfoPropertyName.FILE_NAME.getVal()));
236         return candidateData;
237     }
238
239     private Id addStructureSubElement(SessionContext context, ElementContext elementContext, ElementType elementType, Id parentElementId) {
240         ZusammenElement newElement = buildStructuralElement(elementType, Action.CREATE);
241         ZusammenElement parentElement = buildElement(parentElementId, Action.IGNORE);
242         parentElement.addSubElement(newElement);
243         return zusammenAdaptor.saveElement(context, elementContext, parentElement,
244             String.format("Add element %s under element id %s", elementType.name(), parentElementId)).getSubElements().iterator().next()
245             .getElementId();
246     }
247
248     private void emptyStructureElementAndSub(SessionContext context, ElementContext elementContext, Id elementId, ElementType elementType,
249                                              Id subElementId, ElementType subElementType) {
250         ZusammenElement subElement = buildStructuralElement(subElementType, Action.UPDATE);
251         subElement.setElementId(subElementId);
252         subElement.setData(new ByteArrayInputStream(EMPTY_DATA_BYTES));
253         ZusammenElement element = buildStructuralElement(elementType, Action.UPDATE);
254         element.setElementId(elementId);
255         element.setData(new ByteArrayInputStream(EMPTY_DATA_BYTES));
256         element.addSubElement(subElement);
257         zusammenAdaptor.saveElement(context, elementContext, element,
258             String.format("Empty element %s and its sub element %s", elementType.name(), subElementType.name()));
259     }
260
261     private boolean isNotEmpty(InputStream elementData) {
262         byte[] byteElementData;
263         if (Objects.isNull(elementData)) {
264             return false;
265         }
266         try {
267             byteElementData = IOUtils.toByteArray(elementData);
268         } catch (IOException e) {
269             return true;
270         }
271         return !ArrayUtils.isEmpty(byteElementData);
272     }
273
274     public enum InfoPropertyName {
275         FILE_SUFFIX("fileSuffix"), FILE_NAME("fileName");
276         private String val;
277
278         InfoPropertyName(String val) {
279             this.val = val;
280         }
281
282         private String getVal() {
283             return val;
284         }
285     }
286 }