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 java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
24 import java.util.Objects;
25 import java.util.Optional;
28 import org.apache.commons.collections4.CollectionUtils;
29 import org.apache.commons.collections4.MapUtils;
30 import org.onap.sdc.tosca.datatypes.model.*;
31 import org.onap.sdc.tosca.datatypes.model.heatextend.ParameterDefinitionExt;
32 import org.onap.sdc.tosca.services.YamlUtil;
33 import org.openecomp.core.translator.datatypes.TranslatorOutput;
34 import org.openecomp.core.utilities.file.FileUtils;
35 import org.openecomp.sdc.common.errors.CoreException;
36 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
37 import org.openecomp.sdc.heat.datatypes.model.Environment;
38 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
39 import org.openecomp.sdc.heat.datatypes.model.Output;
40 import org.openecomp.sdc.heat.datatypes.model.Resource;
41 import org.openecomp.sdc.logging.api.Logger;
42 import org.openecomp.sdc.logging.api.LoggerFactory;
43 import org.openecomp.sdc.tosca.datatypes.ToscaGroupType;
44 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
45 import org.openecomp.sdc.tosca.services.DataModelUtil;
46 import org.openecomp.sdc.tosca.services.ToscaConstants;
47 import org.openecomp.sdc.tosca.services.ToscaFileOutputService;
48 import org.openecomp.sdc.tosca.services.ToscaUtil;
49 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
50 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
51 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
52 import org.openecomp.sdc.translator.datatypes.heattotosca.to.FileDataCollection;
53 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
54 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
55 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaParameterConverter;
57 public class TranslationService {
59 protected static Logger logger = LoggerFactory.getLogger(TranslationService.class);
62 * Gets types to process by translator.
64 * @return the types to process by translator
66 public static Set<FileData.Type> getTypesToProcessByTranslator() {
67 Set<FileData.Type> types = new HashSet<>();
68 types.add(FileData.Type.HEAT);
69 types.add(FileData.Type.HEAT_VOL);
73 public static Set<FileData.Type> getTypesToProcessByHelmTranslator() {
74 Set<FileData.Type> types = new HashSet<>();
75 types.add(FileData.Type.HELM);
80 * Translate heat files translator output.
82 * @param translationContext the translation context
83 * @return the translator output
85 public TranslatorOutput translateHeatFiles(TranslationContext translationContext) {
86 ServiceTemplate mainServiceTemplate = createMainServiceTemplate(translationContext);
87 List<FileData> fileDataList = translationContext.getManifest().getContent().getData();
88 FileDataCollection fileDataCollection = HeatToToscaUtil.getFileCollectionsByFilter(fileDataList,
89 TranslationService.getTypesToProcessByTranslator(), translationContext);
90 FileDataCollection fileDataCollectionHelm = HeatToToscaUtil.getFileCollectionsByHelmFilter(fileDataList,
91 TranslationService.getTypesToProcessByHelmTranslator());
93 if (fileDataCollection.getBaseFile() != null) {
94 for (FileData fileData : fileDataCollection.getBaseFile()) {
95 translateHeatFile(mainServiceTemplate, fileData, translationContext);
98 if (fileDataCollection.getAddOnFiles() != null) {
99 for (FileData fileData : fileDataCollection.getAddOnFiles()) {
100 translateHeatFile(mainServiceTemplate, fileData, translationContext);
104 if (fileDataCollectionHelm.getHelmFile() !=null) {
105 for (FileData fileData : fileDataCollectionHelm.getHelmFile()) {
106 translateHelmFile(mainServiceTemplate, fileData, translationContext);
111 ToscaServiceModel toscaServiceModel =
112 HeatToToscaUtil.createToscaServiceModel(mainServiceTemplate, translationContext);
114 TranslatorOutput translatorOutput = new TranslatorOutput();
115 //Keeping a copy of tosca service model after first stage of translation for extraction of
117 translatorOutput.setNonUnifiedToscaServiceModel(
118 ToscaServiceModel.getClonedServiceModel(toscaServiceModel));
119 translatorOutput.setToscaServiceModel(toscaServiceModel);
120 return translatorOutput;
123 private ServiceTemplate createMainServiceTemplate(TranslationContext translationContext) {
124 ServiceTemplate mainServiceTemplate = new ServiceTemplate();
125 translationContext.getTranslatedServiceTemplates()
126 .put(Constants.MAIN_TEMPLATE_NAME, mainServiceTemplate);
127 Map<String, String> templateMetadata = new HashMap<>();
128 templateMetadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME, Constants.MAIN_TEMPLATE_NAME);
129 mainServiceTemplate.setTosca_definitions_version(ToscaConstants.TOSCA_DEFINITIONS_VERSION);
130 mainServiceTemplate.setMetadata(templateMetadata);
131 mainServiceTemplate.setTopology_template(new TopologyTemplate());
132 mainServiceTemplate.setImports(GlobalTypesGenerator.getGlobalTypesImportList());
133 return mainServiceTemplate;
137 * Translate heat file.
139 * @param serviceTemplate the service template
140 * @param heatFileData the heat file data
141 * @param context the context
143 public void translateHeatFile(ServiceTemplate serviceTemplate, FileData heatFileData,
144 TranslationContext context) {
145 String heatFileName = heatFileData.getFile();
146 HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil()
147 .yamlToObject(context.getFileContentAsStream(heatFileName), HeatOrchestrationTemplate.class);
149 translateInputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData, context,
152 translateResources(heatFileName, serviceTemplate, heatOrchestrationTemplate, context);
153 translateOutputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData,
154 heatFileName, context);
155 createHeatStackGroup(serviceTemplate, heatFileData, heatOrchestrationTemplate, context);
156 handleHeatPseudoParam(heatFileName, serviceTemplate, context);
157 if (Objects.nonNull(heatFileData.getData())) {
158 heatFileData.getData().stream().filter(data -> FileData.Type.canBeAssociated(data.getType()))
159 .forEach(data -> translateHeatFile(serviceTemplate, data, context));
164 public void translateHelmFile(ServiceTemplate serviceTemplate, FileData heatFileData,
165 TranslationContext context) {
166 String heatFileName = heatFileData.getFile();
167 Map<String, ParameterDefinition> inputs = serviceTemplate.getTopology_template().getInputs();
168 if (!Objects.isNull(inputs)) {
170 inputs.entrySet().forEach(
171 stringParameterDefinitionEntry -> {
172 List inputParamVFModuleList = getVFModulesList(
173 inputs.get(stringParameterDefinitionEntry.getKey()));
174 if (!inputParamVFModuleList.contains(FileUtils.getFileWithoutExtention(heatFileName)) ){
175 inputParamVFModuleList.add(FileUtils.getFileWithoutExtention(heatFileName));
180 inputs.putAll(inputs);
183 private void handleHeatPseudoParam(String heatFileName, ServiceTemplate serviceTemplate,
184 TranslationContext context) {
185 Map<String, String> translatedHeatPseudoParam =
186 context.getUsedHeatPseudoParams().get(heatFileName);
187 if (Objects.nonNull(translatedHeatPseudoParam)) {
188 for (String heatPseudoParam : translatedHeatPseudoParam.keySet()) {
189 if (!serviceTemplate.getTopology_template().getInputs().containsKey(heatPseudoParam)) {
190 ParameterDefinition parameterDefinition = new ParameterDefinition();
191 parameterDefinition.setType(PropertyType.STRING.getDisplayName());
192 parameterDefinition.setRequired(false);
193 String parameterDefinitionId = translatedHeatPseudoParam.get(heatPseudoParam);
194 DataModelUtil.addInputParameterToTopologyTemplate(serviceTemplate, parameterDefinitionId,
195 parameterDefinition);
201 private void createHeatStackGroup(ServiceTemplate serviceTemplate, FileData heatFileData,
202 HeatOrchestrationTemplate heatOrchestrationTemplate,
203 TranslationContext context) {
204 ToscaFileOutputService toscaFileOutputService = new ToscaFileOutputServiceCsarImpl();
205 final String fileName = heatFileData.getFile();
206 final String heatStackGroupId = FileUtils.getFileWithoutExtention(fileName) + "_group";
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);
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
223 groupDefinition.getMembers().addAll(heatStackGroupMembersIds);
225 .addGroupDefinitionToTopologyTemplate(serviceTemplate, heatStackGroupId, groupDefinition);
228 private Set<String> getHeatStackGroupMembers(String heatFileName,
229 ServiceTemplate serviceTemplate,
230 TranslationContext context) {
232 Map<String, Set<String>> heatStackGroupMembers = context.getHeatStackGroupMembers();
233 Set<String> groupMembers = MapUtils.isEmpty(heatStackGroupMembers) ? new HashSet<>()
234 : heatStackGroupMembers.get(heatFileName);
236 if (CollectionUtils.isEmpty(groupMembers)) {
237 return new HashSet<>();
240 Set<String> updatedMembersIds = new HashSet<>();
242 groupMembers.forEach(member -> {
243 if (Objects.nonNull(DataModelUtil.getNodeTemplate(serviceTemplate, member))) {
244 updatedMembersIds.add(member);
246 updateSubstitutableGroupMemberId(heatFileName, serviceTemplate, updatedMembersIds);
250 return updatedMembersIds;
253 private void updateSubstitutableGroupMemberId(String heatFileName,
254 ServiceTemplate serviceTemplate,
255 Set<String> updatedMembersIds) {
256 Optional<String> substitutableGroupMemberId =
257 ToscaUtil.getSubstitutableGroupMemberId(heatFileName, serviceTemplate);
259 substitutableGroupMemberId.ifPresent(updatedMembersIds::add);
262 private void translateInputParameters(ServiceTemplate serviceTemplate,
263 HeatOrchestrationTemplate heatOrchestrationTemplate,
264 FileData heatFileData, TranslationContext context,
265 String heatFileName) {
266 if (heatOrchestrationTemplate.getParameters() == null) {
270 final Environment heatEnvFile = getHeatEnvFile(heatFileData, context);
271 final Map<String, Object> parameters = heatEnvFile.getParameters();
272 Map<String, ParameterDefinition> parameterDefinitionMap =
273 TranslatorHeatToToscaParameterConverter
274 .parameterConverter(serviceTemplate, heatOrchestrationTemplate.getParameters(),
275 heatOrchestrationTemplate, heatFileName, heatFileData.getParentFile(), context, parameters);
276 Object parameterValue;
277 if (parameters != null) {
278 for (Map.Entry<String, ParameterDefinition> entry : parameterDefinitionMap.entrySet()) {
279 String paramName = entry.getKey();
280 parameterValue = parameters.get(paramName);
281 if (parameterValue != null) {
282 entry.getValue().set_default(TranslatorHeatToToscaParameterConverter
283 .getToscaParameterDefaultValue(null, null, parameterValue, entry.getValue().getType(),
284 heatFileName, heatOrchestrationTemplate, context));
290 Map<String, ParameterDefinition> inputs = serviceTemplate.getTopology_template().getInputs();
291 if (Objects.isNull(inputs)) {
292 serviceTemplate.getTopology_template().setInputs(parameterDefinitionMap);
294 setInputs(inputs, parameterDefinitionMap);
300 private void setInputs(Map<String, ParameterDefinition> inputs, Map<String, ParameterDefinition> newParameters) {
302 updateAnnotations(inputs, newParameters);
303 inputs.putAll(newParameters);
307 private void updateAnnotations(Map<String, ParameterDefinition> inputParameters, Map<String,
308 ParameterDefinition> newParameters) {
309 newParameters.entrySet().stream().filter(stringParameterDefinitionEntry ->
310 inputParameters.containsKey(stringParameterDefinitionEntry.getKey())
311 && isHasAnnotation(inputParameters, stringParameterDefinitionEntry))
312 .forEach(stringParameterDefinitionEntry -> {
313 List inputParamVFModuleList = getVFModulesList(
314 inputParameters.get(stringParameterDefinitionEntry.getKey()));
315 List newParamVFModuleList = getVFModulesList(stringParameterDefinitionEntry.getValue());
316 if (inputParamVFModuleList.contains(newParamVFModuleList.get(0))) {
317 newParamVFModuleList.remove(0);
319 newParamVFModuleList.addAll(inputParamVFModuleList);
324 private boolean isHasAnnotation(Map<String, ParameterDefinition> inputParameters, Map.Entry<String, ParameterDefinition> newParameterSet) {
325 ParameterDefinitionExt inputParameter = (ParameterDefinitionExt) inputParameters.get(newParameterSet.getKey());
326 ParameterDefinitionExt newParameter = (ParameterDefinitionExt) newParameterSet.getValue();
327 return inputParameter.getAnnotations() != null && newParameter.getAnnotations() != null;
330 private List getVFModulesList(ParameterDefinition param) {
331 ParameterDefinitionExt parameterDefinitionExt = (ParameterDefinitionExt) param;
332 return (List) parameterDefinitionExt.getAnnotations().get(ToscaConstants.SOURCE_ANNOTATION_ID).getProperties().
333 get(ToscaConstants.VF_MODULE_LABEL_PROPERTY_NAME);
336 private void translateOutputParameters(ServiceTemplate serviceTemplate,
337 HeatOrchestrationTemplate heatOrchestrationTemplate,
338 FileData heatFileData, String heatFileName,
339 TranslationContext context) {
340 if (heatOrchestrationTemplate.getOutputs() == null) {
343 Map<String, ParameterDefinition> parameterDefinitionMap =
344 TranslatorHeatToToscaParameterConverter
345 .parameterOutputConverter(serviceTemplate, heatOrchestrationTemplate.getOutputs(),
346 heatOrchestrationTemplate, heatFileName, context);
347 if (serviceTemplate.getTopology_template().getOutputs() != null) {
348 serviceTemplate.getTopology_template().getOutputs().putAll(parameterDefinitionMap);
350 serviceTemplate.getTopology_template().setOutputs(parameterDefinitionMap);
353 if (heatFileData.getBase() != null && heatFileData.getBase().equals(true)) {
354 updateSharedResources(serviceTemplate, heatFileName, heatOrchestrationTemplate,
355 heatOrchestrationTemplate.getOutputs(), context);
359 private void updateSharedResources(ServiceTemplate serviceTemplate, String heatFileName,
360 HeatOrchestrationTemplate heatOrchestrationTemplate,
361 Map<String, Output> outputs, TranslationContext context) {
362 for (Map.Entry<String, Output> parameter : outputs.entrySet()) {
363 Optional<AttachedResourceId> attachedSharedResourceId = HeatToToscaUtil
364 .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context,
365 parameter.getValue().getValue());
366 if (attachedSharedResourceId.isPresent() && attachedSharedResourceId.get().isGetResource()
367 && attachedSharedResourceId.get().getTranslatedId() != null) {
368 String sharedTranslatedResourceId =
369 attachedSharedResourceId.get().getTranslatedId().toString();
370 updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
371 heatOrchestrationTemplate.getResources()
372 .get(attachedSharedResourceId.get().getEntityId()));
374 Optional<String> contrailSharedResourceId = HeatToToscaUtil
375 .extractContrailGetResourceAttachedHeatResourceId(parameter.getValue().getValue());
376 if (contrailSharedResourceId.isPresent()
377 && context.getTranslatedIds().get(heatFileName).get(contrailSharedResourceId.get())
379 String sharedTranslatedResourceId = context.getTranslatedIds().get(heatFileName).get
380 (contrailSharedResourceId.get());
381 ConsolidationDataUtil.removeSharedResource(serviceTemplate, heatOrchestrationTemplate,
382 context, parameter.getKey(), contrailSharedResourceId.get(), sharedTranslatedResourceId);
383 updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
384 heatOrchestrationTemplate.getResources().get(contrailSharedResourceId.get()));
388 if (serviceTemplate.getTopology_template().getOutputs() != null
389 && serviceTemplate.getTopology_template().getOutputs().size() == 0) {
390 serviceTemplate.getTopology_template().setOutputs(null);
394 private void updateSharedResource(ServiceTemplate serviceTemplate, TranslationContext context,
395 Map.Entry<String, Output> paramName,
396 String sharedTranslatedResourceId, Resource resource) {
397 context.addHeatSharedResourcesByParam(paramName.getKey(), sharedTranslatedResourceId, resource);
398 serviceTemplate.getTopology_template().getOutputs().remove(paramName.getKey());
401 private void translateResources(String heatFileName, ServiceTemplate serviceTemplate,
402 HeatOrchestrationTemplate heatOrchestrationTemplate,
403 TranslationContext context) {
404 if (MapUtils.isEmpty(heatOrchestrationTemplate.getResources())) {
408 for (String resourceId : heatOrchestrationTemplate.getResources().keySet()) {
409 Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
410 if (resource == null) {
411 throw new CoreException(
412 new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
414 ResourceTranslationFactory.getInstance(resource)
415 .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, resource,
416 resourceId, context);
420 private Environment getHeatEnvFile(FileData heatFileData, TranslationContext context) {
421 List<FileData> fileRelatedDataList = heatFileData.getData();
422 if (fileRelatedDataList == null) {
423 return new Environment();
425 for (FileData fileRelatedData : fileRelatedDataList) {
426 if (fileRelatedData.getType().equals(FileData.Type.HEAT_ENV)) {
427 return new YamlUtil().yamlToObject(context.getFileContentAsStream(fileRelatedData.getFile()),
431 return new Environment();