2 * Copyright © 2016-2018 European Support Limited
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.openecomp.sdc.translator.services.heattotosca;
19 import org.apache.commons.collections4.CollectionUtils;
20 import org.apache.commons.collections4.MapUtils;
21 import org.openecomp.core.translator.datatypes.TranslatorOutput;
22 import org.openecomp.core.utilities.file.FileUtils;
23 import org.openecomp.sdc.common.errors.CoreException;
24 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
25 import org.openecomp.sdc.heat.datatypes.model.Environment;
26 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
27 import org.openecomp.sdc.heat.datatypes.model.Output;
28 import org.openecomp.sdc.heat.datatypes.model.Resource;
29 import org.openecomp.sdc.logging.api.Logger;
30 import org.openecomp.sdc.logging.api.LoggerFactory;
31 import org.openecomp.sdc.tosca.datatypes.ToscaGroupType;
32 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
33 import org.openecomp.sdc.tosca.datatypes.model.GroupDefinition;
34 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
35 import org.openecomp.sdc.tosca.datatypes.model.PropertyType;
36 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
37 import org.openecomp.sdc.tosca.datatypes.model.TopologyTemplate;
38 import org.openecomp.sdc.tosca.datatypes.model.heatextend.ParameterDefinitionExt;
39 import org.openecomp.sdc.tosca.services.DataModelUtil;
40 import org.openecomp.sdc.tosca.services.ToscaConstants;
41 import org.openecomp.sdc.tosca.services.ToscaFileOutputService;
42 import org.openecomp.sdc.tosca.services.ToscaUtil;
43 import org.openecomp.sdc.tosca.services.YamlUtil;
44 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
45 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
46 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
47 import org.openecomp.sdc.translator.datatypes.heattotosca.to.FileDataCollection;
48 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
49 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
50 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaParameterConverter;
52 import java.util.ArrayList;
53 import java.util.HashMap;
54 import java.util.HashSet;
55 import java.util.List;
57 import java.util.Objects;
58 import java.util.Optional;
60 import java.util.stream.Collectors;
62 public class TranslationService {
64 protected static Logger logger = LoggerFactory.getLogger(TranslationService.class);
67 * Gets types to process by translator.
69 * @return the types to process by translator
71 public static Set<FileData.Type> getTypesToProcessByTranslator() {
72 Set<FileData.Type> types = new HashSet<>();
73 types.add(FileData.Type.HEAT);
74 types.add(FileData.Type.HEAT_VOL);
79 * Translate heat files translator output.
81 * @param translationContext the translation context
82 * @return the translator output
84 public TranslatorOutput translateHeatFiles(TranslationContext translationContext) {
85 ServiceTemplate mainServiceTemplate = createMainServiceTemplate(translationContext);
86 List<FileData> fileDataList = translationContext.getManifest().getContent().getData();
87 FileDataCollection fileDataCollection = HeatToToscaUtil.getFileCollectionsByFilter(fileDataList,
88 TranslationService.getTypesToProcessByTranslator(), translationContext);
90 if (fileDataCollection.getBaseFile() != null) {
91 for (FileData fileData : fileDataCollection.getBaseFile()) {
92 translateHeatFile(mainServiceTemplate, fileData, translationContext);
95 if (fileDataCollection.getAddOnFiles() != null) {
96 for (FileData fileData : fileDataCollection.getAddOnFiles()) {
97 translateHeatFile(mainServiceTemplate, fileData, translationContext);
101 ToscaServiceModel toscaServiceModel =
102 HeatToToscaUtil.createToscaServiceModel(mainServiceTemplate, translationContext);
104 TranslatorOutput translatorOutput = new TranslatorOutput();
105 //Keeping a copy of tosca service model after first stage of translation for extraction of
107 translatorOutput.setNonUnifiedToscaServiceModel(
108 ToscaServiceModel.getClonedServiceModel(toscaServiceModel));
109 translatorOutput.setToscaServiceModel(toscaServiceModel);
110 return translatorOutput;
113 private ServiceTemplate createMainServiceTemplate(TranslationContext translationContext) {
114 ServiceTemplate mainServiceTemplate = new ServiceTemplate();
115 translationContext.getTranslatedServiceTemplates()
116 .put(Constants.MAIN_TEMPLATE_NAME, mainServiceTemplate);
117 Map<String, String> templateMetadata = new HashMap<>();
118 templateMetadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME, Constants.MAIN_TEMPLATE_NAME);
119 mainServiceTemplate.setTosca_definitions_version(ToscaConstants.TOSCA_DEFINITIONS_VERSION);
120 mainServiceTemplate.setMetadata(templateMetadata);
121 mainServiceTemplate.setTopology_template(new TopologyTemplate());
122 mainServiceTemplate.setImports(GlobalTypesGenerator.getGlobalTypesImportList());
123 return mainServiceTemplate;
127 * Translate heat file.
129 * @param serviceTemplate the service template
130 * @param heatFileData the heat file data
131 * @param context the context
133 public void translateHeatFile(ServiceTemplate serviceTemplate, FileData heatFileData,
134 TranslationContext context) {
135 translateHeatFile(serviceTemplate, heatFileData, null, context);
139 * Translate heat file.
141 * @param serviceTemplate the service template
142 * @param heatFileData the current heat file data
143 * @param parentHeatFileName the main heat to which associated current heat file (e.g. volume heat)
144 * @param context the context
146 public void translateHeatFile(ServiceTemplate serviceTemplate, FileData heatFileData, String parentHeatFileName,
147 TranslationContext context) {
148 String heatFileName = heatFileData.getFile();
149 HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil()
150 .yamlToObject(context.getFileContent(heatFileName), HeatOrchestrationTemplate.class);
152 translateInputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData, context,
153 heatFileName, parentHeatFileName);
154 translateResources(heatFileName, serviceTemplate, heatOrchestrationTemplate, context);
155 translateOutputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData,
156 heatFileName, context);
157 createHeatStackGroup(serviceTemplate, heatFileData, heatOrchestrationTemplate, context);
158 handleHeatPseudoParam(heatFileName, serviceTemplate, context);
160 if (Objects.nonNull(heatFileData.getData())) {
161 heatFileData.getData().stream().filter(data -> data.getType() == FileData.Type.HEAT_VOL)
162 .forEach(data -> translateHeatFile(serviceTemplate, data, heatFileData.getFile(), context));
166 private void handleHeatPseudoParam(String heatFileName, ServiceTemplate serviceTemplate,
167 TranslationContext context) {
168 Map<String, String> translatedHeatPseudoParam =
169 context.getUsedHeatPseudoParams().get(heatFileName);
170 if (Objects.nonNull(translatedHeatPseudoParam)) {
171 for (String heatPseudoParam : translatedHeatPseudoParam.keySet()) {
172 if (!serviceTemplate.getTopology_template().getInputs().containsKey(heatPseudoParam)) {
173 ParameterDefinition parameterDefinition = new ParameterDefinition();
174 parameterDefinition.setType(PropertyType.STRING.getDisplayName());
175 parameterDefinition.setRequired(false);
176 String parameterDefinitionId = translatedHeatPseudoParam.get(heatPseudoParam);
177 DataModelUtil.addInputParameterToTopologyTemplate(serviceTemplate, parameterDefinitionId,
178 parameterDefinition);
184 private void createHeatStackGroup(ServiceTemplate serviceTemplate, FileData heatFileData,
185 HeatOrchestrationTemplate heatOrchestrationTemplate,
186 TranslationContext context) {
187 ToscaFileOutputService toscaFileOutputService = new ToscaFileOutputServiceCsarImpl();
188 final String fileName = heatFileData.getFile();
189 final String heatStackGroupId = FileUtils.getFileWithoutExtention(fileName) + "_group";
191 GroupDefinition groupDefinition = new GroupDefinition();
192 groupDefinition.setType(ToscaGroupType.HEAT_STACK);
193 groupDefinition.setProperties(new HashMap<>());
194 groupDefinition.getProperties()
195 .put("heat_file", "../" + toscaFileOutputService.getArtifactsFolderName() + "/" + fileName);
196 String hotDescription = heatOrchestrationTemplate.getDescription();
197 if (hotDescription != null && !hotDescription.isEmpty()) {
198 groupDefinition.getProperties().put(Constants.DESCRIPTION_PROPERTY_NAME, hotDescription);
200 groupDefinition.setMembers(new ArrayList<>());
201 Set<String> heatStackGroupMembersIds = getHeatStackGroupMembers(fileName,
202 serviceTemplate, context);
203 if (CollectionUtils.isEmpty(heatStackGroupMembersIds)) {
204 return; //not creating a group when no resources are present in the heat input
206 groupDefinition.getMembers().addAll(heatStackGroupMembersIds);
208 .addGroupDefinitionToTopologyTemplate(serviceTemplate, heatStackGroupId, groupDefinition);
211 private Set<String> getHeatStackGroupMembers(String heatFileName,
212 ServiceTemplate serviceTemplate,
213 TranslationContext context) {
215 Map<String, Set<String>> heatStackGroupMembers = context.getHeatStackGroupMembers();
216 Set<String> groupMembers = MapUtils.isEmpty(heatStackGroupMembers) ? new HashSet<>()
217 : heatStackGroupMembers.get(heatFileName);
219 if (CollectionUtils.isEmpty(groupMembers)) {
220 return new HashSet<>();
223 Set<String> updatedMembersIds = new HashSet<>();
225 groupMembers.forEach(member -> {
226 if (Objects.nonNull(DataModelUtil.getNodeTemplate(serviceTemplate, member))) {
227 updatedMembersIds.add(member);
229 updateSubstitutableGroupMemberId(heatFileName, serviceTemplate, updatedMembersIds);
233 return updatedMembersIds;
236 private void updateSubstitutableGroupMemberId(String heatFileName,
237 ServiceTemplate serviceTemplate,
238 Set<String> updatedMembersIds) {
239 Optional<String> substitutableGroupMemberId =
240 ToscaUtil.getSubstitutableGroupMemberId(heatFileName, serviceTemplate);
242 substitutableGroupMemberId.ifPresent(updatedMembersIds::add);
245 private void translateInputParameters(ServiceTemplate serviceTemplate,
246 HeatOrchestrationTemplate heatOrchestrationTemplate,
247 FileData heatFileData, TranslationContext context,
248 String heatFileName, String parentHeatFileName) {
249 if (heatOrchestrationTemplate.getParameters() == null) {
253 Map<String, ParameterDefinition> parameterDefinitionMap =
254 TranslatorHeatToToscaParameterConverter
255 .parameterConverter(serviceTemplate, heatOrchestrationTemplate.getParameters(),
256 heatOrchestrationTemplate, heatFileName, parentHeatFileName, context);
257 Environment heatEnvFile = getHeatEnvFile(heatFileData, context);
258 Map<String, Object> parameters = heatEnvFile.getParameters();
259 Object parameterValue;
260 if (parameters != null) {
261 for (Map.Entry<String, ParameterDefinition> entry : parameterDefinitionMap.entrySet()) {
262 String paramName = entry.getKey();
263 parameterValue = parameters.get(paramName);
264 if (parameterValue != null) {
265 entry.getValue().set_default(TranslatorHeatToToscaParameterConverter
266 .getToscaParameterDefaultValue(null, null, parameterValue, entry.getValue().getType(),
267 heatFileName, heatOrchestrationTemplate, context));
273 Map<String, ParameterDefinition> inputs = serviceTemplate.getTopology_template().getInputs();
274 if (Objects.isNull(inputs)) {
275 serviceTemplate.getTopology_template().setInputs(parameterDefinitionMap);
277 setInputs(inputs, parameterDefinitionMap);
283 private void setInputs(Map<String, ParameterDefinition> inputs, Map<String, ParameterDefinition> newParameters) {
285 updateAnnotations(inputs, newParameters);
286 inputs.putAll(newParameters);
290 private void updateAnnotations(Map<String, ParameterDefinition> inputParameters, Map<String, ParameterDefinition> newParameters) {
292 newParameters.entrySet().stream().filter(stringParameterDefinitionEntry ->
293 inputParameters.containsKey(stringParameterDefinitionEntry.getKey()) &&
294 isHasAnnotation(inputParameters, stringParameterDefinitionEntry)).
295 forEach(stringParameterDefinitionEntry -> {
296 List inputParamVFModuleList = getVFModulesList(inputParameters.get(stringParameterDefinitionEntry.getKey()));
297 List newParamVFModuleList = getVFModulesList(stringParameterDefinitionEntry.getValue());
298 if(inputParamVFModuleList.contains(newParamVFModuleList.get(0))){
299 newParamVFModuleList.remove(0);
301 newParamVFModuleList.addAll(inputParamVFModuleList);
307 private boolean isHasAnnotation(Map<String, ParameterDefinition> inputParameters, Map.Entry<String, ParameterDefinition> newParameterSet) {
308 ParameterDefinitionExt inputParameter = (ParameterDefinitionExt) inputParameters.get(newParameterSet.getKey());
309 ParameterDefinitionExt newParameter = (ParameterDefinitionExt) newParameterSet.getValue();
310 return inputParameter.getAnnotations() != null && newParameter.getAnnotations() != null;
313 private List getVFModulesList(ParameterDefinition param) {
314 ParameterDefinitionExt parameterDefinitionExt = (ParameterDefinitionExt) param;
315 return (List) parameterDefinitionExt.getAnnotations().get(ToscaConstants.SOURCE_ANNOTATION_ID).getProperties().
316 get(ToscaConstants.VF_MODULE_LABEL_PROPERTY_NAME);
319 private void translateOutputParameters(ServiceTemplate serviceTemplate,
320 HeatOrchestrationTemplate heatOrchestrationTemplate,
321 FileData heatFileData, String heatFileName,
322 TranslationContext context) {
323 if (heatOrchestrationTemplate.getOutputs() == null) {
326 Map<String, ParameterDefinition> parameterDefinitionMap =
327 TranslatorHeatToToscaParameterConverter
328 .parameterOutputConverter(serviceTemplate, heatOrchestrationTemplate.getOutputs(),
329 heatOrchestrationTemplate, heatFileName, context);
330 if (serviceTemplate.getTopology_template().getOutputs() != null) {
331 serviceTemplate.getTopology_template().getOutputs().putAll(parameterDefinitionMap);
333 serviceTemplate.getTopology_template().setOutputs(parameterDefinitionMap);
336 if (heatFileData.getBase() != null && heatFileData.getBase().equals(true)) {
337 updateSharedResources(serviceTemplate, heatFileName, heatOrchestrationTemplate,
338 heatOrchestrationTemplate.getOutputs(), context);
342 private void updateSharedResources(ServiceTemplate serviceTemplate, String heatFileName,
343 HeatOrchestrationTemplate heatOrchestrationTemplate,
344 Map<String, Output> outputs, TranslationContext context) {
345 for (Map.Entry<String, Output> parameter : outputs.entrySet()) {
346 Optional<AttachedResourceId> attachedSharedResourceId = HeatToToscaUtil
347 .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context,
348 parameter.getValue().getValue());
349 if (attachedSharedResourceId.isPresent() && attachedSharedResourceId.get().isGetResource()
350 && attachedSharedResourceId.get().getTranslatedId() != null) {
351 String sharedTranslatedResourceId =
352 attachedSharedResourceId.get().getTranslatedId().toString();
353 updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
354 heatOrchestrationTemplate.getResources()
355 .get(attachedSharedResourceId.get().getEntityId()));
357 Optional<String> contrailSharedResourceId = HeatToToscaUtil
358 .extractContrailGetResourceAttachedHeatResourceId(parameter.getValue().getValue());
359 if (contrailSharedResourceId.isPresent()
360 && context.getTranslatedIds().get(heatFileName).get(contrailSharedResourceId.get())
362 String sharedTranslatedResourceId = context.getTranslatedIds().get(heatFileName).get
363 (contrailSharedResourceId.get());
364 ConsolidationDataUtil.removeSharedResource(serviceTemplate, heatOrchestrationTemplate,
365 context, parameter.getKey(), contrailSharedResourceId.get(), sharedTranslatedResourceId);
366 updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
367 heatOrchestrationTemplate.getResources().get(contrailSharedResourceId.get()));
371 if (serviceTemplate.getTopology_template().getOutputs() != null
372 && serviceTemplate.getTopology_template().getOutputs().size() == 0) {
373 serviceTemplate.getTopology_template().setOutputs(null);
377 private void updateSharedResource(ServiceTemplate serviceTemplate, TranslationContext context,
378 Map.Entry<String, Output> paramName,
379 String sharedTranslatedResourceId, Resource resource) {
380 context.addHeatSharedResourcesByParam(paramName.getKey(), sharedTranslatedResourceId, resource);
381 serviceTemplate.getTopology_template().getOutputs().remove(paramName.getKey());
384 private void translateResources(String heatFileName, ServiceTemplate serviceTemplate,
385 HeatOrchestrationTemplate heatOrchestrationTemplate,
386 TranslationContext context) {
387 if (MapUtils.isEmpty(heatOrchestrationTemplate.getResources())) {
391 for (String resourceId : heatOrchestrationTemplate.getResources().keySet()) {
392 Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
393 if (resource == null) {
394 throw new CoreException(
395 new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
397 ResourceTranslationFactory.getInstance(resource)
398 .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, resource,
399 resourceId, context);
403 private Environment getHeatEnvFile(FileData heatFileData, TranslationContext context) {
404 List<FileData> fileRelatedDataList = heatFileData.getData();
405 if (fileRelatedDataList == null) {
406 return new Environment();
408 for (FileData fileRelatedData : fileRelatedDataList) {
409 if (fileRelatedData.getType().equals(FileData.Type.HEAT_ENV)) {
410 return new YamlUtil().yamlToObject(context.getFileContent(fileRelatedData.getFile()),
414 return new Environment();