Remove enter/exit debug #6
[sdc.git] / openecomp-be / lib / openecomp-sdc-translator-lib / openecomp-sdc-translator-core / src / main / java / org / openecomp / sdc / translator / services / heattotosca / TranslationService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. 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
21 package org.openecomp.sdc.translator.services.heattotosca;
22
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.core.translator.datatypes.TranslatorOutput;
26 import org.openecomp.core.utilities.file.FileUtils;
27 import org.openecomp.sdc.common.errors.CoreException;
28 import org.openecomp.sdc.datatypes.error.ErrorLevel;
29 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
30 import org.openecomp.sdc.heat.datatypes.model.Environment;
31 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
32 import org.openecomp.sdc.heat.datatypes.model.Output;
33 import org.openecomp.sdc.heat.datatypes.model.Resource;
34 import org.openecomp.sdc.logging.api.Logger;
35 import org.openecomp.sdc.logging.api.LoggerFactory;
36 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
37 import org.openecomp.sdc.logging.types.LoggerConstants;
38 import org.openecomp.sdc.logging.types.LoggerErrorCode;
39 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
40 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
41 import org.openecomp.sdc.tosca.datatypes.ToscaGroupType;
42 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
43 import org.openecomp.sdc.tosca.datatypes.model.GroupDefinition;
44 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
45 import org.openecomp.sdc.tosca.datatypes.model.PropertyType;
46 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
47 import org.openecomp.sdc.tosca.datatypes.model.TopologyTemplate;
48 import org.openecomp.sdc.tosca.services.DataModelUtil;
49 import org.openecomp.sdc.tosca.services.ToscaConstants;
50 import org.openecomp.sdc.tosca.services.ToscaFileOutputService;
51 import org.openecomp.sdc.tosca.services.ToscaUtil;
52 import org.openecomp.sdc.tosca.services.YamlUtil;
53 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
54 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
55 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
56 import org.openecomp.sdc.translator.datatypes.heattotosca.to.FileDataCollection;
57 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
58 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
59 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaParameterConverter;
60
61 import java.util.ArrayList;
62 import java.util.HashMap;
63 import java.util.HashSet;
64 import java.util.List;
65 import java.util.Map;
66 import java.util.Objects;
67 import java.util.Optional;
68 import java.util.Set;
69
70 public class TranslationService {
71
72   protected static Logger logger = (Logger) LoggerFactory.getLogger(TranslationService.class);
73   /**
74    * Gets types to process by translator.
75    *
76    * @return the types to process by translator
77    */
78   public static Set<FileData.Type> getTypesToProcessByTranslator() {
79     Set<FileData.Type> types = new HashSet<>();
80     types.add(FileData.Type.HEAT);
81     types.add(FileData.Type.HEAT_VOL);
82     return types;
83   }
84
85   /**
86    * Translate heat files translator output.
87    *
88    * @param translationContext the translation context
89    * @return the translator output
90    */
91   public TranslatorOutput translateHeatFiles(TranslationContext translationContext) {
92     ServiceTemplate mainServiceTemplate = createMainServiceTemplate(translationContext);
93     List<FileData> fileDataList = translationContext.getManifest().getContent().getData();
94     FileDataCollection fileDataCollection = HeatToToscaUtil.getFileCollectionsByFilter(fileDataList,
95         TranslationService.getTypesToProcessByTranslator(), translationContext);
96
97     if (fileDataCollection.getBaseFile() != null) {
98       for (FileData fileData : fileDataCollection.getBaseFile()) {
99         translateHeatFile(mainServiceTemplate, fileData, translationContext);
100       }
101     }
102     if (fileDataCollection.getAddOnFiles() != null) {
103       for (FileData fileData : fileDataCollection.getAddOnFiles()) {
104         translateHeatFile(mainServiceTemplate, fileData, translationContext);
105       }
106     }
107
108     ToscaServiceModel toscaServiceModel =
109         HeatToToscaUtil.createToscaServiceModel(mainServiceTemplate, translationContext);
110
111     TranslatorOutput translatorOutput = new TranslatorOutput();
112     //Keeping a copy of tosca service model after first stage of translation for extraction of
113     // composition data
114     translatorOutput.setNonUnifiedToscaServiceModel(
115         ToscaServiceModel.getClonedServiceModel(toscaServiceModel));
116     translatorOutput.setToscaServiceModel(toscaServiceModel);
117     return translatorOutput;
118   }
119
120   private ServiceTemplate createMainServiceTemplate(TranslationContext translationContext) {
121     ServiceTemplate mainServiceTemplate = new ServiceTemplate();
122     translationContext.getTranslatedServiceTemplates()
123         .put(Constants.MAIN_TEMPLATE_NAME, mainServiceTemplate);
124     Map<String, String> templateMetadata = new HashMap<>();
125     templateMetadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME, Constants.MAIN_TEMPLATE_NAME);
126     mainServiceTemplate.setTosca_definitions_version(ToscaConstants.TOSCA_DEFINITIONS_VERSION);
127     mainServiceTemplate.setMetadata(templateMetadata);
128     mainServiceTemplate.setTopology_template(new TopologyTemplate());
129     mainServiceTemplate.setImports(GlobalTypesGenerator.getGlobalTypesImportList());
130     return mainServiceTemplate;
131   }
132
133   /**
134    * Translate heat file.
135    *
136    * @param serviceTemplate the service template
137    * @param heatFileData    the heat file data
138    * @param context         the context
139    */
140   public void translateHeatFile(ServiceTemplate serviceTemplate, FileData heatFileData,
141                                 TranslationContext context) {
142     String heatFileName = heatFileData.getFile();
143     HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil()
144         .yamlToObject(context.getFileContent(heatFileName), HeatOrchestrationTemplate.class);
145
146     translateInputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData, context,
147         heatFileName);
148     translateResources(heatFileName, serviceTemplate, heatOrchestrationTemplate, context);
149     translateOutputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData,
150         heatFileName, context);
151     createHeatStackGroup(serviceTemplate, heatFileData, heatOrchestrationTemplate, context);
152     handleHeatPseudoParam(heatFileName, serviceTemplate, context);
153
154     if (Objects.nonNull(heatFileData.getData())) {
155       heatFileData.getData().stream().filter(data -> data.getType() == FileData.Type.HEAT_VOL)
156           .forEach(data -> translateHeatFile(serviceTemplate, data, context));
157     }
158   }
159
160   private void handleHeatPseudoParam(String heatFileName, ServiceTemplate serviceTemplate,
161                                      TranslationContext context) {
162     Map<String, String> translatedHeatPseudoParam =
163         context.getUsedHeatPseudoParams().get(heatFileName);
164     if (Objects.nonNull(translatedHeatPseudoParam)) {
165       for (String heatPseudoParam : translatedHeatPseudoParam.keySet()) {
166         if (!serviceTemplate.getTopology_template().getInputs().containsKey(heatPseudoParam)) {
167           ParameterDefinition parameterDefinition = new ParameterDefinition();
168           parameterDefinition.setType(PropertyType.STRING.getDisplayName());
169           parameterDefinition.setRequired(false);
170           String parameterDefinitionId = translatedHeatPseudoParam.get(heatPseudoParam);
171           DataModelUtil.addInputParameterToTopologyTemplate(serviceTemplate, parameterDefinitionId,
172               parameterDefinition);
173         }
174       }
175     }
176   }
177
178   private void createHeatStackGroup(ServiceTemplate serviceTemplate, FileData heatFileData,
179                                     HeatOrchestrationTemplate heatOrchestrationTemplate,
180                                     TranslationContext context) {
181     ToscaFileOutputService toscaFileOutputService = new ToscaFileOutputServiceCsarImpl();
182     final String fileName = heatFileData.getFile();
183     final String heatStackGroupId = FileUtils.getFileWithoutExtention(fileName) + "_group";
184
185     GroupDefinition groupDefinition = new GroupDefinition();
186     groupDefinition.setType(ToscaGroupType.HEAT_STACK);
187     groupDefinition.setProperties(new HashMap<>());
188     groupDefinition.getProperties()
189         .put("heat_file", "../" + toscaFileOutputService.getArtifactsFolderName() + "/" + fileName);
190     String hotDescription = heatOrchestrationTemplate.getDescription();
191     if (hotDescription != null && !hotDescription.isEmpty()) {
192       groupDefinition.getProperties().put(Constants.DESCRIPTION_PROPERTY_NAME, hotDescription);
193     }
194     groupDefinition.setMembers(new ArrayList<>());
195     Set<String> heatStackGroupMembersIds = getHeatStackGroupMembers(fileName,
196         serviceTemplate, context);
197     if (CollectionUtils.isEmpty(heatStackGroupMembersIds)) {
198       return; //not creating a group when no resources are present in the heat input
199     }
200     groupDefinition.getMembers().addAll(heatStackGroupMembersIds);
201     DataModelUtil
202         .addGroupDefinitionToTopologyTemplate(serviceTemplate, heatStackGroupId, groupDefinition);
203   }
204
205   private Set<String> getHeatStackGroupMembers(String heatFileName,
206                                                             ServiceTemplate serviceTemplate,
207                                                             TranslationContext context){
208
209     Map<String, Set<String>> heatStackGroupMembers = context.getHeatStackGroupMembers();
210     Set<String> groupMembers = MapUtils.isEmpty(heatStackGroupMembers) ? new HashSet<>()
211         : heatStackGroupMembers.get(heatFileName);
212
213     if(CollectionUtils.isEmpty(groupMembers)){
214       return new HashSet<>();
215     }
216
217     Set<String> updatedMembersIds = new HashSet<>();
218
219     groupMembers.forEach(member -> {
220       if (Objects.nonNull(DataModelUtil.getNodeTemplate(serviceTemplate, member))) {
221         updatedMembersIds.add(member);
222       } else {
223         updateSubstitutableGroupMemberId(heatFileName, serviceTemplate, updatedMembersIds);
224       }
225     });
226
227     return updatedMembersIds;
228   }
229
230   private void updateSubstitutableGroupMemberId(String heatFileName,
231                                                 ServiceTemplate serviceTemplate,
232                                                 Set<String> updatedMembersIds) {
233     Optional<String> substitutableGroupMemberId =
234         ToscaUtil.getSubstitutableGroupMemberId(heatFileName, serviceTemplate);
235
236     if (substitutableGroupMemberId.isPresent()) {
237       updatedMembersIds.add(substitutableGroupMemberId.get());
238     }
239   }
240
241   private void translateInputParameters(ServiceTemplate serviceTemplate,
242                                         HeatOrchestrationTemplate heatOrchestrationTemplate,
243                                         FileData heatFileData, TranslationContext context,
244                                         String heatFileName) {
245     if (heatOrchestrationTemplate.getParameters() == null) {
246       return;
247     }
248
249     Map<String, ParameterDefinition> parameterDefinitionMap =
250         TranslatorHeatToToscaParameterConverter
251             .parameterConverter(serviceTemplate,heatOrchestrationTemplate.getParameters(),
252                 heatOrchestrationTemplate, heatFileName, context);
253     Environment heatEnvFile = getHeatEnvFile(heatFileData, context);
254     Map<String, Object> parameters = heatEnvFile.getParameters();
255     Object parameterValue;
256     if (parameters != null) {
257       for (Map.Entry<String, ParameterDefinition> entry : parameterDefinitionMap.entrySet()) {
258         String paramName = entry.getKey();
259         parameterValue = parameters.get(paramName);
260         if (parameterValue != null) {
261           entry.getValue().set_default(TranslatorHeatToToscaParameterConverter
262               .getToscaParameterDefaultValue(null, null, parameterValue, entry.getValue().getType(),
263                   heatFileName, heatOrchestrationTemplate, context));
264         }
265       }
266     }
267
268     Map<String, ParameterDefinition> inputs = serviceTemplate.getTopology_template().getInputs();
269     if (Objects.isNull(inputs)) {
270       serviceTemplate.getTopology_template().setInputs(parameterDefinitionMap);
271     } else {
272       inputs.putAll(parameterDefinitionMap);
273     }
274   }
275
276   private void translateOutputParameters(ServiceTemplate serviceTemplate,
277                                          HeatOrchestrationTemplate heatOrchestrationTemplate,
278                                          FileData heatFileData, String heatFileName,
279                                          TranslationContext context) {
280     if (heatOrchestrationTemplate.getOutputs() == null) {
281       return;
282     }
283     Map<String, ParameterDefinition> parameterDefinitionMap =
284         TranslatorHeatToToscaParameterConverter
285             .parameterOutputConverter(serviceTemplate,heatOrchestrationTemplate.getOutputs(),
286                 heatOrchestrationTemplate, heatFileName, context);
287     if (serviceTemplate.getTopology_template().getOutputs() != null) {
288       serviceTemplate.getTopology_template().getOutputs().putAll(parameterDefinitionMap);
289     } else {
290       serviceTemplate.getTopology_template().setOutputs(parameterDefinitionMap);
291     }
292
293     if (heatFileData.getBase() != null && heatFileData.getBase().equals(true)) {
294       updateSharedResources(serviceTemplate, heatFileName, heatOrchestrationTemplate,
295           heatOrchestrationTemplate.getOutputs(), context);
296     }
297   }
298
299   private void updateSharedResources(ServiceTemplate serviceTemplate, String heatFileName,
300                                      HeatOrchestrationTemplate heatOrchestrationTemplate,
301                                      Map<String, Output> outputs, TranslationContext context) {
302     for (Map.Entry<String, Output> parameter : outputs.entrySet()) {
303       Optional<AttachedResourceId> attachedSharedResourceId = HeatToToscaUtil
304           .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context,
305               parameter.getValue().getValue());
306       if (attachedSharedResourceId.isPresent() && attachedSharedResourceId.get().isGetResource()
307           && attachedSharedResourceId.get().getTranslatedId() != null) {
308         String sharedTranslatedResourceId =
309             attachedSharedResourceId.get().getTranslatedId().toString();
310         updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
311             heatOrchestrationTemplate.getResources()
312                 .get(attachedSharedResourceId.get().getEntityId()));
313       } else {
314         Optional<String> contrailSharedResourceId = HeatToToscaUtil
315             .extractContrailGetResourceAttachedHeatResourceId(parameter.getValue().getValue());
316         if (contrailSharedResourceId.isPresent()
317             && context.getTranslatedIds().get(heatFileName).get(contrailSharedResourceId.get())
318             != null) {
319           String sharedTranslatedResourceId = context.getTranslatedIds().get(heatFileName).get
320               (contrailSharedResourceId.get());
321           ConsolidationDataUtil.removeSharedResource(serviceTemplate, heatOrchestrationTemplate,
322               context, parameter.getKey(),contrailSharedResourceId.get(), sharedTranslatedResourceId);
323           updateSharedResource(serviceTemplate, context, parameter,sharedTranslatedResourceId,
324               heatOrchestrationTemplate.getResources().get(contrailSharedResourceId.get()));
325         }
326       }
327     }
328     if (serviceTemplate.getTopology_template().getOutputs() != null
329         && serviceTemplate.getTopology_template().getOutputs().size() == 0) {
330       serviceTemplate.getTopology_template().setOutputs(null);
331     }
332   }
333
334   private void updateSharedResource(ServiceTemplate serviceTemplate, TranslationContext context,
335                                     Map.Entry<String, Output> paramName,
336                                     String sharedTranslatedResourceId, Resource resource) {
337     context.addHeatSharedResourcesByParam(paramName.getKey(), sharedTranslatedResourceId, resource);
338     serviceTemplate.getTopology_template().getOutputs().remove(paramName.getKey());
339   }
340
341   private void translateResources(String heatFileName, ServiceTemplate serviceTemplate,
342                                   HeatOrchestrationTemplate heatOrchestrationTemplate,
343                                   TranslationContext context) {
344     if(MapUtils.isEmpty(heatOrchestrationTemplate.getResources())){
345       return;
346     }
347
348     for (String resourceId : heatOrchestrationTemplate.getResources().keySet()) {
349       Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
350       if (resource == null) {
351         MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
352             LoggerTragetServiceName.TRANSLATE_RESOURCE, ErrorLevel.ERROR.name(),
353             LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.TRANSLATE_HEAT);
354         throw new CoreException(
355             new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
356       }
357       ResourceTranslationFactory.getInstance(resource)
358           .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, resource,
359               resourceId, context);
360     }
361   }
362
363   private Environment getHeatEnvFile(FileData heatFileData, TranslationContext context) {
364     List<FileData> fileRelatedDataList = heatFileData.getData();
365     if (fileRelatedDataList == null) {
366       return new Environment();
367     }
368     for (FileData fileRelatedData : fileRelatedDataList) {
369       if (fileRelatedData.getType().equals(FileData.Type.HEAT_ENV)) {
370         return new YamlUtil().yamlToObject(context.getFileContent(fileRelatedData.getFile()),
371             Environment.class);
372       }
373     }
374     return new Environment();
375   }
376
377
378 }