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.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.tosca.datatypes.ToscaGroupType;
36 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
37 import org.openecomp.sdc.tosca.datatypes.model.GroupDefinition;
38 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
39 import org.openecomp.sdc.tosca.datatypes.model.PropertyType;
40 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
41 import org.openecomp.sdc.tosca.datatypes.model.TopologyTemplate;
42 import org.openecomp.sdc.tosca.services.DataModelUtil;
43 import org.openecomp.sdc.tosca.services.ToscaConstants;
44 import org.openecomp.sdc.tosca.services.ToscaFileOutputService;
45 import org.openecomp.sdc.tosca.services.ToscaUtil;
46 import org.openecomp.sdc.tosca.services.YamlUtil;
47 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
48 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
49 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
50 import org.openecomp.sdc.translator.datatypes.heattotosca.to.FileDataCollection;
51 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
52 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
53 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaParameterConverter;
55 import java.util.ArrayList;
56 import java.util.HashMap;
57 import java.util.HashSet;
58 import java.util.List;
60 import java.util.Objects;
61 import java.util.Optional;
64 public class TranslationService {
66 protected static Logger logger = LoggerFactory.getLogger(TranslationService.class);
68 * Gets types to process by translator.
70 * @return the types to process by translator
72 public static Set<FileData.Type> getTypesToProcessByTranslator() {
73 Set<FileData.Type> types = new HashSet<>();
74 types.add(FileData.Type.HEAT);
75 types.add(FileData.Type.HEAT_VOL);
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);
91 if (fileDataCollection.getBaseFile() != null) {
92 for (FileData fileData : fileDataCollection.getBaseFile()) {
93 translateHeatFile(mainServiceTemplate, fileData, translationContext);
96 if (fileDataCollection.getAddOnFiles() != null) {
97 for (FileData fileData : fileDataCollection.getAddOnFiles()) {
98 translateHeatFile(mainServiceTemplate, fileData, translationContext);
102 ToscaServiceModel toscaServiceModel =
103 HeatToToscaUtil.createToscaServiceModel(mainServiceTemplate, translationContext);
105 TranslatorOutput translatorOutput = new TranslatorOutput();
106 //Keeping a copy of tosca service model after first stage of translation for extraction of
108 translatorOutput.setNonUnifiedToscaServiceModel(
109 ToscaServiceModel.getClonedServiceModel(toscaServiceModel));
110 translatorOutput.setToscaServiceModel(toscaServiceModel);
111 return translatorOutput;
114 private ServiceTemplate createMainServiceTemplate(TranslationContext translationContext) {
115 ServiceTemplate mainServiceTemplate = new ServiceTemplate();
116 translationContext.getTranslatedServiceTemplates()
117 .put(Constants.MAIN_TEMPLATE_NAME, mainServiceTemplate);
118 Map<String, String> templateMetadata = new HashMap<>();
119 templateMetadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME, Constants.MAIN_TEMPLATE_NAME);
120 mainServiceTemplate.setTosca_definitions_version(ToscaConstants.TOSCA_DEFINITIONS_VERSION);
121 mainServiceTemplate.setMetadata(templateMetadata);
122 mainServiceTemplate.setTopology_template(new TopologyTemplate());
123 mainServiceTemplate.setImports(GlobalTypesGenerator.getGlobalTypesImportList());
124 return mainServiceTemplate;
128 * Translate heat file.
130 * @param serviceTemplate the service template
131 * @param heatFileData the heat file data
132 * @param context the context
134 public void translateHeatFile(ServiceTemplate serviceTemplate, FileData heatFileData,
135 TranslationContext context) {
136 String heatFileName = heatFileData.getFile();
137 HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil()
138 .yamlToObject(context.getFileContent(heatFileName), HeatOrchestrationTemplate.class);
140 translateInputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData, context,
142 translateResources(heatFileName, serviceTemplate, heatOrchestrationTemplate, context);
143 translateOutputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData,
144 heatFileName, context);
145 createHeatStackGroup(serviceTemplate, heatFileData, heatOrchestrationTemplate, context);
146 handleHeatPseudoParam(heatFileName, serviceTemplate, context);
148 if (Objects.nonNull(heatFileData.getData())) {
149 heatFileData.getData().stream().filter(data -> data.getType() == FileData.Type.HEAT_VOL)
150 .forEach(data -> translateHeatFile(serviceTemplate, data, context));
154 private void handleHeatPseudoParam(String heatFileName, ServiceTemplate serviceTemplate,
155 TranslationContext context) {
156 Map<String, String> translatedHeatPseudoParam =
157 context.getUsedHeatPseudoParams().get(heatFileName);
158 if (Objects.nonNull(translatedHeatPseudoParam)) {
159 for (String heatPseudoParam : translatedHeatPseudoParam.keySet()) {
160 if (!serviceTemplate.getTopology_template().getInputs().containsKey(heatPseudoParam)) {
161 ParameterDefinition parameterDefinition = new ParameterDefinition();
162 parameterDefinition.setType(PropertyType.STRING.getDisplayName());
163 parameterDefinition.setRequired(false);
164 String parameterDefinitionId = translatedHeatPseudoParam.get(heatPseudoParam);
165 DataModelUtil.addInputParameterToTopologyTemplate(serviceTemplate, parameterDefinitionId,
166 parameterDefinition);
172 private void createHeatStackGroup(ServiceTemplate serviceTemplate, FileData heatFileData,
173 HeatOrchestrationTemplate heatOrchestrationTemplate,
174 TranslationContext context) {
175 ToscaFileOutputService toscaFileOutputService = new ToscaFileOutputServiceCsarImpl();
176 final String fileName = heatFileData.getFile();
177 final String heatStackGroupId = FileUtils.getFileWithoutExtention(fileName) + "_group";
179 GroupDefinition groupDefinition = new GroupDefinition();
180 groupDefinition.setType(ToscaGroupType.HEAT_STACK);
181 groupDefinition.setProperties(new HashMap<>());
182 groupDefinition.getProperties()
183 .put("heat_file", "../" + toscaFileOutputService.getArtifactsFolderName() + "/" + fileName);
184 String hotDescription = heatOrchestrationTemplate.getDescription();
185 if (hotDescription != null && !hotDescription.isEmpty()) {
186 groupDefinition.getProperties().put(Constants.DESCRIPTION_PROPERTY_NAME, hotDescription);
188 groupDefinition.setMembers(new ArrayList<>());
189 Set<String> heatStackGroupMembersIds = getHeatStackGroupMembers(fileName,
190 serviceTemplate, context);
191 if (CollectionUtils.isEmpty(heatStackGroupMembersIds)) {
192 return; //not creating a group when no resources are present in the heat input
194 groupDefinition.getMembers().addAll(heatStackGroupMembersIds);
196 .addGroupDefinitionToTopologyTemplate(serviceTemplate, heatStackGroupId, groupDefinition);
199 private Set<String> getHeatStackGroupMembers(String heatFileName,
200 ServiceTemplate serviceTemplate,
201 TranslationContext context){
203 Map<String, Set<String>> heatStackGroupMembers = context.getHeatStackGroupMembers();
204 Set<String> groupMembers = MapUtils.isEmpty(heatStackGroupMembers) ? new HashSet<>()
205 : heatStackGroupMembers.get(heatFileName);
207 if(CollectionUtils.isEmpty(groupMembers)){
208 return new HashSet<>();
211 Set<String> updatedMembersIds = new HashSet<>();
213 groupMembers.forEach(member -> {
214 if (Objects.nonNull(DataModelUtil.getNodeTemplate(serviceTemplate, member))) {
215 updatedMembersIds.add(member);
217 updateSubstitutableGroupMemberId(heatFileName, serviceTemplate, updatedMembersIds);
221 return updatedMembersIds;
224 private void updateSubstitutableGroupMemberId(String heatFileName,
225 ServiceTemplate serviceTemplate,
226 Set<String> updatedMembersIds) {
227 Optional<String> substitutableGroupMemberId =
228 ToscaUtil.getSubstitutableGroupMemberId(heatFileName, serviceTemplate);
230 substitutableGroupMemberId.ifPresent(updatedMembersIds::add);
233 private void translateInputParameters(ServiceTemplate serviceTemplate,
234 HeatOrchestrationTemplate heatOrchestrationTemplate,
235 FileData heatFileData, TranslationContext context,
236 String heatFileName) {
237 if (heatOrchestrationTemplate.getParameters() == null) {
241 Map<String, ParameterDefinition> parameterDefinitionMap =
242 TranslatorHeatToToscaParameterConverter
243 .parameterConverter(serviceTemplate,heatOrchestrationTemplate.getParameters(),
244 heatOrchestrationTemplate, heatFileName, context);
245 Environment heatEnvFile = getHeatEnvFile(heatFileData, context);
246 Map<String, Object> parameters = heatEnvFile.getParameters();
247 Object parameterValue;
248 if (parameters != null) {
249 for (Map.Entry<String, ParameterDefinition> entry : parameterDefinitionMap.entrySet()) {
250 String paramName = entry.getKey();
251 parameterValue = parameters.get(paramName);
252 if (parameterValue != null) {
253 entry.getValue().set_default(TranslatorHeatToToscaParameterConverter
254 .getToscaParameterDefaultValue(null, null, parameterValue, entry.getValue().getType(),
255 heatFileName, heatOrchestrationTemplate, context));
260 Map<String, ParameterDefinition> inputs = serviceTemplate.getTopology_template().getInputs();
261 if (Objects.isNull(inputs)) {
262 serviceTemplate.getTopology_template().setInputs(parameterDefinitionMap);
264 inputs.putAll(parameterDefinitionMap);
268 private void translateOutputParameters(ServiceTemplate serviceTemplate,
269 HeatOrchestrationTemplate heatOrchestrationTemplate,
270 FileData heatFileData, String heatFileName,
271 TranslationContext context) {
272 if (heatOrchestrationTemplate.getOutputs() == null) {
275 Map<String, ParameterDefinition> parameterDefinitionMap =
276 TranslatorHeatToToscaParameterConverter
277 .parameterOutputConverter(serviceTemplate,heatOrchestrationTemplate.getOutputs(),
278 heatOrchestrationTemplate, heatFileName, context);
279 if (serviceTemplate.getTopology_template().getOutputs() != null) {
280 serviceTemplate.getTopology_template().getOutputs().putAll(parameterDefinitionMap);
282 serviceTemplate.getTopology_template().setOutputs(parameterDefinitionMap);
285 if (heatFileData.getBase() != null && heatFileData.getBase().equals(true)) {
286 updateSharedResources(serviceTemplate, heatFileName, heatOrchestrationTemplate,
287 heatOrchestrationTemplate.getOutputs(), context);
291 private void updateSharedResources(ServiceTemplate serviceTemplate, String heatFileName,
292 HeatOrchestrationTemplate heatOrchestrationTemplate,
293 Map<String, Output> outputs, TranslationContext context) {
294 for (Map.Entry<String, Output> parameter : outputs.entrySet()) {
295 Optional<AttachedResourceId> attachedSharedResourceId = HeatToToscaUtil
296 .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context,
297 parameter.getValue().getValue());
298 if (attachedSharedResourceId.isPresent() && attachedSharedResourceId.get().isGetResource()
299 && attachedSharedResourceId.get().getTranslatedId() != null) {
300 String sharedTranslatedResourceId =
301 attachedSharedResourceId.get().getTranslatedId().toString();
302 updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
303 heatOrchestrationTemplate.getResources()
304 .get(attachedSharedResourceId.get().getEntityId()));
306 Optional<String> contrailSharedResourceId = HeatToToscaUtil
307 .extractContrailGetResourceAttachedHeatResourceId(parameter.getValue().getValue());
308 if (contrailSharedResourceId.isPresent()
309 && context.getTranslatedIds().get(heatFileName).get(contrailSharedResourceId.get())
311 String sharedTranslatedResourceId = context.getTranslatedIds().get(heatFileName).get
312 (contrailSharedResourceId.get());
313 ConsolidationDataUtil.removeSharedResource(serviceTemplate, heatOrchestrationTemplate,
314 context, parameter.getKey(),contrailSharedResourceId.get(), sharedTranslatedResourceId);
315 updateSharedResource(serviceTemplate, context, parameter,sharedTranslatedResourceId,
316 heatOrchestrationTemplate.getResources().get(contrailSharedResourceId.get()));
320 if (serviceTemplate.getTopology_template().getOutputs() != null
321 && serviceTemplate.getTopology_template().getOutputs().size() == 0) {
322 serviceTemplate.getTopology_template().setOutputs(null);
326 private void updateSharedResource(ServiceTemplate serviceTemplate, TranslationContext context,
327 Map.Entry<String, Output> paramName,
328 String sharedTranslatedResourceId, Resource resource) {
329 context.addHeatSharedResourcesByParam(paramName.getKey(), sharedTranslatedResourceId, resource);
330 serviceTemplate.getTopology_template().getOutputs().remove(paramName.getKey());
333 private void translateResources(String heatFileName, ServiceTemplate serviceTemplate,
334 HeatOrchestrationTemplate heatOrchestrationTemplate,
335 TranslationContext context) {
336 if(MapUtils.isEmpty(heatOrchestrationTemplate.getResources())){
340 for (String resourceId : heatOrchestrationTemplate.getResources().keySet()) {
341 Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
342 if (resource == null) {
343 throw new CoreException(
344 new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
346 ResourceTranslationFactory.getInstance(resource)
347 .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, resource,
348 resourceId, context);
352 private Environment getHeatEnvFile(FileData heatFileData, TranslationContext context) {
353 List<FileData> fileRelatedDataList = heatFileData.getData();
354 if (fileRelatedDataList == null) {
355 return new Environment();
357 for (FileData fileRelatedData : fileRelatedDataList) {
358 if (fileRelatedData.getType().equals(FileData.Type.HEAT_ENV)) {
359 return new YamlUtil().yamlToObject(context.getFileContent(fileRelatedData.getFile()),
363 return new Environment();