2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.translator.services.heattotosca;
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;
61 import java.util.ArrayList;
62 import java.util.HashMap;
63 import java.util.HashSet;
64 import java.util.List;
66 import java.util.Objects;
67 import java.util.Optional;
70 public class TranslationService {
72 protected static Logger logger = (Logger) LoggerFactory.getLogger(TranslationService.class);
74 * Gets types to process by translator.
76 * @return the types to process by translator
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);
86 * Translate heat files translator output.
88 * @param translationContext the translation context
89 * @return the translator output
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);
97 if (fileDataCollection.getBaseFile() != null) {
98 for (FileData fileData : fileDataCollection.getBaseFile()) {
99 translateHeatFile(mainServiceTemplate, fileData, translationContext);
102 if (fileDataCollection.getAddOnFiles() != null) {
103 for (FileData fileData : fileDataCollection.getAddOnFiles()) {
104 translateHeatFile(mainServiceTemplate, fileData, translationContext);
108 ToscaServiceModel toscaServiceModel =
109 HeatToToscaUtil.createToscaServiceModel(mainServiceTemplate, translationContext);
111 TranslatorOutput translatorOutput = new TranslatorOutput();
112 //Keeping a copy of tosca service model after first stage of translation for extraction of
114 translatorOutput.setNonUnifiedToscaServiceModel(
115 ToscaServiceModel.getClonedServiceModel(toscaServiceModel));
116 translatorOutput.setToscaServiceModel(toscaServiceModel);
117 return translatorOutput;
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;
134 * Translate heat file.
136 * @param serviceTemplate the service template
137 * @param heatFileData the heat file data
138 * @param context the context
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);
146 translateInputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData, context,
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);
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));
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);
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";
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);
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
200 groupDefinition.getMembers().addAll(heatStackGroupMembersIds);
202 .addGroupDefinitionToTopologyTemplate(serviceTemplate, heatStackGroupId, groupDefinition);
205 private Set<String> getHeatStackGroupMembers(String heatFileName,
206 ServiceTemplate serviceTemplate,
207 TranslationContext context){
209 Map<String, Set<String>> heatStackGroupMembers = context.getHeatStackGroupMembers();
210 Set<String> groupMembers = MapUtils.isEmpty(heatStackGroupMembers) ? new HashSet<>()
211 : heatStackGroupMembers.get(heatFileName);
213 if(CollectionUtils.isEmpty(groupMembers)){
214 return new HashSet<>();
217 Set<String> updatedMembersIds = new HashSet<>();
219 groupMembers.forEach(member -> {
220 if (Objects.nonNull(DataModelUtil.getNodeTemplate(serviceTemplate, member))) {
221 updatedMembersIds.add(member);
223 updateSubstitutableGroupMemberId(heatFileName, serviceTemplate, updatedMembersIds);
227 return updatedMembersIds;
230 private void updateSubstitutableGroupMemberId(String heatFileName,
231 ServiceTemplate serviceTemplate,
232 Set<String> updatedMembersIds) {
233 Optional<String> substitutableGroupMemberId =
234 ToscaUtil.getSubstitutableGroupMemberId(heatFileName, serviceTemplate);
236 if (substitutableGroupMemberId.isPresent()) {
237 updatedMembersIds.add(substitutableGroupMemberId.get());
241 private void translateInputParameters(ServiceTemplate serviceTemplate,
242 HeatOrchestrationTemplate heatOrchestrationTemplate,
243 FileData heatFileData, TranslationContext context,
244 String heatFileName) {
245 if (heatOrchestrationTemplate.getParameters() == null) {
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));
268 Map<String, ParameterDefinition> inputs = serviceTemplate.getTopology_template().getInputs();
269 if (Objects.isNull(inputs)) {
270 serviceTemplate.getTopology_template().setInputs(parameterDefinitionMap);
272 inputs.putAll(parameterDefinitionMap);
276 private void translateOutputParameters(ServiceTemplate serviceTemplate,
277 HeatOrchestrationTemplate heatOrchestrationTemplate,
278 FileData heatFileData, String heatFileName,
279 TranslationContext context) {
280 if (heatOrchestrationTemplate.getOutputs() == null) {
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);
290 serviceTemplate.getTopology_template().setOutputs(parameterDefinitionMap);
293 if (heatFileData.getBase() != null && heatFileData.getBase().equals(true)) {
294 updateSharedResources(serviceTemplate, heatFileName, heatOrchestrationTemplate,
295 heatOrchestrationTemplate.getOutputs(), context);
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()));
314 Optional<String> contrailSharedResourceId = HeatToToscaUtil
315 .extractContrailGetResourceAttachedHeatResourceId(parameter.getValue().getValue());
316 if (contrailSharedResourceId.isPresent()
317 && context.getTranslatedIds().get(heatFileName).get(contrailSharedResourceId.get())
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()));
328 if (serviceTemplate.getTopology_template().getOutputs() != null
329 && serviceTemplate.getTopology_template().getOutputs().size() == 0) {
330 serviceTemplate.getTopology_template().setOutputs(null);
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());
341 private void translateResources(String heatFileName, ServiceTemplate serviceTemplate,
342 HeatOrchestrationTemplate heatOrchestrationTemplate,
343 TranslationContext context) {
344 if(MapUtils.isEmpty(heatOrchestrationTemplate.getResources())){
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());
357 ResourceTranslationFactory.getInstance(resource)
358 .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, resource,
359 resourceId, context);
363 private Environment getHeatEnvFile(FileData heatFileData, TranslationContext context) {
364 List<FileData> fileRelatedDataList = heatFileData.getData();
365 if (fileRelatedDataList == null) {
366 return new Environment();
368 for (FileData fileRelatedData : fileRelatedDataList) {
369 if (fileRelatedData.getType().equals(FileData.Type.HEAT_ENV)) {
370 return new YamlUtil().yamlToObject(context.getFileContent(fileRelatedData.getFile()),
374 return new Environment();