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