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