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.
16 package org.openecomp.sdc.translator.services.heattotosca;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.List;
23 import java.util.Objects;
24 import java.util.Optional;
26 import org.apache.commons.collections4.CollectionUtils;
27 import org.apache.commons.collections4.MapUtils;
28 import org.onap.sdc.tosca.datatypes.model.GroupDefinition;
29 import org.onap.sdc.tosca.datatypes.model.ParameterDefinition;
30 import org.onap.sdc.tosca.datatypes.model.PropertyType;
31 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
32 import org.onap.sdc.tosca.datatypes.model.TopologyTemplate;
33 import org.onap.sdc.tosca.datatypes.model.heatextend.ParameterDefinitionExt;
34 import org.onap.sdc.tosca.services.YamlUtil;
35 import org.openecomp.core.translator.datatypes.TranslatorOutput;
36 import org.openecomp.core.utilities.file.FileUtils;
37 import org.openecomp.sdc.common.errors.CoreException;
38 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
39 import org.openecomp.sdc.heat.datatypes.model.Environment;
40 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
41 import org.openecomp.sdc.heat.datatypes.model.Output;
42 import org.openecomp.sdc.heat.datatypes.model.Resource;
43 import org.openecomp.sdc.logging.api.Logger;
44 import org.openecomp.sdc.logging.api.LoggerFactory;
45 import org.openecomp.sdc.tosca.datatypes.ToscaGroupType;
46 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
47 import org.openecomp.sdc.tosca.services.DataModelUtil;
48 import org.openecomp.sdc.tosca.services.ToscaConstants;
49 import org.openecomp.sdc.tosca.services.ToscaFileOutputService;
50 import org.openecomp.sdc.tosca.services.ToscaUtil;
51 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
52 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
53 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
54 import org.openecomp.sdc.translator.datatypes.heattotosca.to.FileDataCollection;
55 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
56 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
57 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaParameterConverter;
59 public class TranslationService {
61 protected static Logger logger = LoggerFactory.getLogger(TranslationService.class);
64 * Gets types to process by translator.
66 * @return the types to process by translator
68 public static Set<FileData.Type> getTypesToProcessByTranslator() {
69 Set<FileData.Type> types = new HashSet<>();
70 types.add(FileData.Type.HEAT);
71 types.add(FileData.Type.HEAT_VOL);
75 public static Set<FileData.Type> getTypesToProcessByHelmTranslator() {
76 Set<FileData.Type> types = new HashSet<>();
77 types.add(FileData.Type.HELM);
82 * Translate heat files translator output.
84 * @param translationContext the translation context
85 * @return the translator output
87 public TranslatorOutput translateHeatFiles(TranslationContext translationContext) {
88 ServiceTemplate mainServiceTemplate = createMainServiceTemplate(translationContext);
89 List<FileData> fileDataList = translationContext.getManifest().getContent().getData();
90 FileDataCollection fileDataCollection = HeatToToscaUtil
91 .getFileCollectionsByFilter(fileDataList, TranslationService.getTypesToProcessByTranslator(), translationContext);
92 FileDataCollection fileDataCollectionHelm = HeatToToscaUtil
93 .getFileCollectionsByHelmFilter(fileDataList, TranslationService.getTypesToProcessByHelmTranslator());
94 if (fileDataCollection.getBaseFile() != null) {
95 for (FileData fileData : fileDataCollection.getBaseFile()) {
96 translateHeatFile(mainServiceTemplate, fileData, translationContext);
99 if (fileDataCollection.getAddOnFiles() != null) {
100 for (FileData fileData : fileDataCollection.getAddOnFiles()) {
101 translateHeatFile(mainServiceTemplate, fileData, translationContext);
104 if (fileDataCollectionHelm.getHelmFile() != null) {
105 for (FileData fileData : fileDataCollectionHelm.getHelmFile()) {
106 translateHelmFile(mainServiceTemplate, fileData, translationContext);
109 ToscaServiceModel toscaServiceModel = HeatToToscaUtil.createToscaServiceModel(mainServiceTemplate, translationContext);
110 TranslatorOutput translatorOutput = new TranslatorOutput();
111 //Keeping a copy of tosca service model after first stage of translation for extraction of
114 translatorOutput.setNonUnifiedToscaServiceModel(ToscaServiceModel.getClonedServiceModel(toscaServiceModel));
115 translatorOutput.setToscaServiceModel(toscaServiceModel);
116 return translatorOutput;
119 private ServiceTemplate createMainServiceTemplate(TranslationContext translationContext) {
120 ServiceTemplate mainServiceTemplate = new ServiceTemplate();
121 translationContext.getTranslatedServiceTemplates().put(Constants.MAIN_TEMPLATE_NAME, mainServiceTemplate);
122 Map<String, String> templateMetadata = new HashMap<>();
123 templateMetadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME, Constants.MAIN_TEMPLATE_NAME);
124 mainServiceTemplate.setTosca_definitions_version(ToscaConstants.TOSCA_DEFINITIONS_VERSION);
125 mainServiceTemplate.setMetadata(templateMetadata);
126 mainServiceTemplate.setTopology_template(new TopologyTemplate());
127 mainServiceTemplate.setImports(GlobalTypesGenerator.getGlobalTypesImportList());
128 return mainServiceTemplate;
132 * Translate heat file.
134 * @param serviceTemplate the service template
135 * @param heatFileData the heat file data
136 * @param context the context
138 public void translateHeatFile(ServiceTemplate serviceTemplate, FileData heatFileData, TranslationContext context) {
139 String heatFileName = heatFileData.getFile();
140 HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil()
141 .yamlToObject(context.getFileContentAsStream(heatFileName), HeatOrchestrationTemplate.class);
142 translateInputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData, context, heatFileName);
143 translateResources(heatFileName, serviceTemplate, heatOrchestrationTemplate, context);
144 translateOutputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData, heatFileName, context);
145 createHeatStackGroup(serviceTemplate, heatFileData, heatOrchestrationTemplate, context);
146 handleHeatPseudoParam(heatFileName, serviceTemplate, context);
147 if (Objects.nonNull(heatFileData.getData())) {
148 heatFileData.getData().stream().filter(data -> FileData.Type.canBeAssociated(data.getType()))
149 .forEach(data -> translateHeatFile(serviceTemplate, data, context));
153 public void translateHelmFile(ServiceTemplate serviceTemplate, FileData heatFileData, TranslationContext context) {
154 String heatFileName = heatFileData.getFile();
155 Map<String, ParameterDefinition> inputs = serviceTemplate.getTopology_template().getInputs();
156 if (!Objects.isNull(inputs)) {
157 inputs.entrySet().forEach(stringParameterDefinitionEntry -> {
158 List inputParamVFModuleList = getVFModulesList(inputs.get(stringParameterDefinitionEntry.getKey()));
159 if (!inputParamVFModuleList.contains(FileUtils.getFileWithoutExtention(heatFileName))) {
160 inputParamVFModuleList.add(FileUtils.getFileWithoutExtention(heatFileName));
164 inputs.putAll(inputs);
167 private void handleHeatPseudoParam(String heatFileName, ServiceTemplate serviceTemplate, TranslationContext context) {
168 Map<String, String> translatedHeatPseudoParam = context.getUsedHeatPseudoParams().get(heatFileName);
169 if (Objects.nonNull(translatedHeatPseudoParam)) {
170 for (String heatPseudoParam : translatedHeatPseudoParam.keySet()) {
171 if (!serviceTemplate.getTopology_template().getInputs().containsKey(heatPseudoParam)) {
172 ParameterDefinition parameterDefinition = new ParameterDefinition();
173 parameterDefinition.setType(PropertyType.STRING.getDisplayName());
174 parameterDefinition.setRequired(false);
175 String parameterDefinitionId = translatedHeatPseudoParam.get(heatPseudoParam);
176 DataModelUtil.addInputParameterToTopologyTemplate(serviceTemplate, parameterDefinitionId, parameterDefinition);
182 private void createHeatStackGroup(ServiceTemplate serviceTemplate, FileData heatFileData, HeatOrchestrationTemplate heatOrchestrationTemplate,
183 TranslationContext context) {
184 ToscaFileOutputService toscaFileOutputService = new ToscaFileOutputServiceCsarImpl();
185 final String fileName = heatFileData.getFile();
186 final String heatStackGroupId = FileUtils.getFileWithoutExtention(fileName) + "_group";
187 GroupDefinition groupDefinition = new GroupDefinition();
188 groupDefinition.setType(ToscaGroupType.HEAT_STACK);
189 groupDefinition.setProperties(new HashMap<>());
190 groupDefinition.getProperties().put("heat_file", "../" + toscaFileOutputService.getArtifactsFolderName() + "/" + fileName);
191 String hotDescription = heatOrchestrationTemplate.getDescription();
192 if (hotDescription != null && !hotDescription.isEmpty()) {
193 groupDefinition.getProperties().put(Constants.DESCRIPTION_PROPERTY_NAME, hotDescription);
195 groupDefinition.setMembers(new ArrayList<>());
196 Set<String> heatStackGroupMembersIds = getHeatStackGroupMembers(fileName, 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);
201 DataModelUtil.addGroupDefinitionToTopologyTemplate(serviceTemplate, heatStackGroupId, groupDefinition);
204 private Set<String> getHeatStackGroupMembers(String heatFileName, ServiceTemplate serviceTemplate, TranslationContext context) {
205 Map<String, Set<String>> heatStackGroupMembers = context.getHeatStackGroupMembers();
206 Set<String> groupMembers = MapUtils.isEmpty(heatStackGroupMembers) ? new HashSet<>() : heatStackGroupMembers.get(heatFileName);
207 if (CollectionUtils.isEmpty(groupMembers)) {
208 return new HashSet<>();
210 Set<String> updatedMembersIds = new HashSet<>();
211 groupMembers.forEach(member -> {
212 if (Objects.nonNull(DataModelUtil.getNodeTemplate(serviceTemplate, member))) {
213 updatedMembersIds.add(member);
215 updateSubstitutableGroupMemberId(heatFileName, serviceTemplate, updatedMembersIds);
218 return updatedMembersIds;
221 private void updateSubstitutableGroupMemberId(String heatFileName, ServiceTemplate serviceTemplate, Set<String> updatedMembersIds) {
222 Optional<String> substitutableGroupMemberId = ToscaUtil.getSubstitutableGroupMemberId(heatFileName, serviceTemplate);
223 substitutableGroupMemberId.ifPresent(updatedMembersIds::add);
226 private void translateInputParameters(ServiceTemplate serviceTemplate, HeatOrchestrationTemplate heatOrchestrationTemplate, FileData heatFileData,
227 TranslationContext context, String heatFileName) {
228 if (heatOrchestrationTemplate.getParameters() == null) {
231 final Environment heatEnvFile = getHeatEnvFile(heatFileData, context);
232 final Map<String, Object> parameters = heatEnvFile.getParameters();
233 Map<String, ParameterDefinition> parameterDefinitionMap = TranslatorHeatToToscaParameterConverter
234 .parameterConverter(serviceTemplate, heatOrchestrationTemplate.getParameters(), heatOrchestrationTemplate, heatFileName,
235 heatFileData.getParentFile(), context, parameters);
236 Object parameterValue;
237 if (parameters != null) {
238 for (Map.Entry<String, ParameterDefinition> entry : parameterDefinitionMap.entrySet()) {
239 String paramName = entry.getKey();
240 parameterValue = parameters.get(paramName);
241 if (parameterValue != null) {
242 entry.getValue().set_default(TranslatorHeatToToscaParameterConverter
243 .getToscaParameterDefaultValue(null, null, parameterValue, entry.getValue().getType(), heatFileName,
244 heatOrchestrationTemplate, context));
248 Map<String, ParameterDefinition> inputs = serviceTemplate.getTopology_template().getInputs();
249 if (Objects.isNull(inputs)) {
250 serviceTemplate.getTopology_template().setInputs(parameterDefinitionMap);
252 setInputs(inputs, parameterDefinitionMap);
256 private void setInputs(Map<String, ParameterDefinition> inputs, Map<String, ParameterDefinition> newParameters) {
257 updateAnnotations(inputs, newParameters);
258 inputs.putAll(newParameters);
261 private void updateAnnotations(Map<String, ParameterDefinition> inputParameters, Map<String, ParameterDefinition> newParameters) {
262 newParameters.entrySet().stream().filter(
263 stringParameterDefinitionEntry -> inputParameters.containsKey(stringParameterDefinitionEntry.getKey()) && isHasAnnotation(inputParameters,
264 stringParameterDefinitionEntry)).forEach(stringParameterDefinitionEntry -> {
265 List inputParamVFModuleList = getVFModulesList(inputParameters.get(stringParameterDefinitionEntry.getKey()));
266 List newParamVFModuleList = getVFModulesList(stringParameterDefinitionEntry.getValue());
267 if (inputParamVFModuleList.contains(newParamVFModuleList.get(0))) {
268 newParamVFModuleList.remove(0);
270 newParamVFModuleList.addAll(inputParamVFModuleList);
274 private boolean isHasAnnotation(Map<String, ParameterDefinition> inputParameters, Map.Entry<String, ParameterDefinition> newParameterSet) {
275 ParameterDefinitionExt inputParameter = (ParameterDefinitionExt) inputParameters.get(newParameterSet.getKey());
276 ParameterDefinitionExt newParameter = (ParameterDefinitionExt) newParameterSet.getValue();
277 return inputParameter.getAnnotations() != null && newParameter.getAnnotations() != null;
280 private List getVFModulesList(ParameterDefinition param) {
281 ParameterDefinitionExt parameterDefinitionExt = (ParameterDefinitionExt) param;
282 return (List) parameterDefinitionExt.getAnnotations().get(ToscaConstants.SOURCE_ANNOTATION_ID).getProperties()
283 .get(ToscaConstants.VF_MODULE_LABEL_PROPERTY_NAME);
286 private void translateOutputParameters(ServiceTemplate serviceTemplate, HeatOrchestrationTemplate heatOrchestrationTemplate,
287 FileData heatFileData, String heatFileName, TranslationContext context) {
288 if (heatOrchestrationTemplate.getOutputs() == null) {
291 Map<String, ParameterDefinition> parameterDefinitionMap = TranslatorHeatToToscaParameterConverter
292 .parameterOutputConverter(serviceTemplate, heatOrchestrationTemplate.getOutputs(), heatOrchestrationTemplate, heatFileName, context);
293 if (serviceTemplate.getTopology_template().getOutputs() != null) {
294 serviceTemplate.getTopology_template().getOutputs().putAll(parameterDefinitionMap);
296 serviceTemplate.getTopology_template().setOutputs(parameterDefinitionMap);
298 if (heatFileData.getBase() != null && heatFileData.getBase().equals(true)) {
299 updateSharedResources(serviceTemplate, heatFileName, heatOrchestrationTemplate, heatOrchestrationTemplate.getOutputs(), context);
303 private void updateSharedResources(ServiceTemplate serviceTemplate, String heatFileName, HeatOrchestrationTemplate heatOrchestrationTemplate,
304 Map<String, Output> outputs, TranslationContext context) {
305 for (Map.Entry<String, Output> parameter : outputs.entrySet()) {
306 Optional<AttachedResourceId> attachedSharedResourceId = HeatToToscaUtil
307 .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context, parameter.getValue().getValue());
308 if (attachedSharedResourceId.isPresent() && attachedSharedResourceId.get().isGetResource()
309 && attachedSharedResourceId.get().getTranslatedId() != null) {
310 String sharedTranslatedResourceId = attachedSharedResourceId.get().getTranslatedId().toString();
311 updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
312 heatOrchestrationTemplate.getResources().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()) != null) {
318 String sharedTranslatedResourceId = context.getTranslatedIds().get(heatFileName).get(contrailSharedResourceId.get());
319 ConsolidationDataUtil
320 .removeSharedResource(serviceTemplate, heatOrchestrationTemplate, context, parameter.getKey(), contrailSharedResourceId.get(),
321 sharedTranslatedResourceId);
322 updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
323 heatOrchestrationTemplate.getResources().get(contrailSharedResourceId.get()));
327 if (serviceTemplate.getTopology_template().getOutputs() != null && serviceTemplate.getTopology_template().getOutputs().size() == 0) {
328 serviceTemplate.getTopology_template().setOutputs(null);
332 private void updateSharedResource(ServiceTemplate serviceTemplate, TranslationContext context, Map.Entry<String, Output> paramName,
333 String sharedTranslatedResourceId, Resource resource) {
334 context.addHeatSharedResourcesByParam(paramName.getKey(), sharedTranslatedResourceId, resource);
335 serviceTemplate.getTopology_template().getOutputs().remove(paramName.getKey());
338 private void translateResources(String heatFileName, ServiceTemplate serviceTemplate, HeatOrchestrationTemplate heatOrchestrationTemplate,
339 TranslationContext context) {
340 if (MapUtils.isEmpty(heatOrchestrationTemplate.getResources())) {
343 for (String resourceId : heatOrchestrationTemplate.getResources().keySet()) {
344 Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
345 if (resource == null) {
346 throw new CoreException(new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
348 ResourceTranslationFactory.getInstance(resource)
349 .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, resource, resourceId, context);
353 private Environment getHeatEnvFile(FileData heatFileData, TranslationContext context) {
354 List<FileData> fileRelatedDataList = heatFileData.getData();
355 if (fileRelatedDataList == null) {
356 return new Environment();
358 for (FileData fileRelatedData : fileRelatedDataList) {
359 if (fileRelatedData.getType().equals(FileData.Type.HEAT_ENV)) {
360 return new YamlUtil().yamlToObject(context.getFileContentAsStream(fileRelatedData.getFile()), Environment.class);
363 return new Environment();