0fc65c1f947cde3d6fa3158be3ab580b362c27a2
[sdc.git] /
1 /*
2  * -
3  *  * ============LICENSE_START=======================================================
4  *  *  Copyright (C) 2019  Nordix Foundation.
5  *  * ================================================================================
6  *  * Licensed under the Apache License, Version 2.0 (the "License");
7  *  * you may not use this file except in compliance with the License.
8  *  * You may obtain a copy of the License at
9  *  *
10  *  *      http://www.apache.org/licenses/LICENSE-2.0
11  *  *
12  *  * Unless required by applicable law or agreed to in writing, software
13  *  * distributed under the License is distributed on an "AS IS" BASIS,
14  *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  * See the License for the specific language governing permissions and
16  *  * limitations under the License.
17  *  *
18  *  * SPDX-License-Identifier: Apache-2.0
19  *  * ============LICENSE_END=========================================================
20  *
21  */
22
23 package org.openecomp.core.impl;
24
25 import org.apache.commons.collections.MapUtils;
26 import org.onap.sdc.tosca.datatypes.model.ArtifactDefinition;
27 import org.onap.sdc.tosca.datatypes.model.CapabilityAssignment;
28 import org.onap.sdc.tosca.datatypes.model.Import;
29 import org.onap.sdc.tosca.datatypes.model.NodeFilter;
30 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
31 import org.onap.sdc.tosca.datatypes.model.NodeType;
32 import org.onap.sdc.tosca.datatypes.model.ParameterDefinition;
33 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
34 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
35 import org.onap.sdc.tosca.datatypes.model.SubstitutionMapping;
36 import org.openecomp.core.converter.ServiceTemplateReaderService;
37 import org.openecomp.core.converter.ToscaConverter;
38 import org.openecomp.core.converter.datatypes.Constants;
39 import org.openecomp.core.converter.datatypes.CsarFileTypes;
40 import org.openecomp.core.converter.errors.SubstitutionMappingsConverterErrorBuilder;
41 import org.openecomp.core.impl.services.ServiceTemplateReaderServiceImpl;
42 import org.openecomp.core.utilities.file.FileContentHandler;
43 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
44 import org.openecomp.sdc.common.errors.CoreException;
45 import org.openecomp.sdc.common.errors.ErrorCategory;
46 import org.openecomp.sdc.common.errors.ErrorCode;
47 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
48 import org.openecomp.sdc.tosca.services.DataModelUtil;
49 import org.openecomp.sdc.tosca.services.ToscaUtil;
50 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
51 import org.yaml.snakeyaml.error.YAMLException;
52 import java.io.File;
53 import java.io.IOException;
54 import java.util.ArrayList;
55 import java.util.Collection;
56 import java.util.HashMap;
57 import java.util.List;
58 import java.util.Map;
59 import java.util.Objects;
60 import java.util.Optional;
61 import java.util.regex.Pattern;
62
63 import static org.openecomp.core.converter.datatypes.Constants.ONAP_INDEX;
64 import static org.openecomp.core.converter.datatypes.Constants.capabilities;
65 import static org.openecomp.core.converter.datatypes.Constants.definitionsDir;
66 import static org.openecomp.core.converter.datatypes.Constants.globalStName;
67 import static org.openecomp.core.converter.datatypes.Constants.globalSubstitution;
68 import static org.openecomp.core.converter.datatypes.Constants.inputs;
69 import static org.openecomp.core.converter.datatypes.Constants.mainStName;
70 import static org.openecomp.core.converter.datatypes.Constants.nodeType;
71 import static org.openecomp.core.converter.datatypes.Constants.openecompHeatIndex;
72 import static org.openecomp.core.converter.datatypes.Constants.outputs;
73 import static org.openecomp.core.converter.datatypes.Constants.requirements;
74 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME;
75 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.HEAT_INDEX_IMPORT_FILE;
76 import static org.openecomp.core.impl.GlobalSubstitutionServiceTemplate.ONAP_INDEX_IMPORT_FILE;
77 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ORIG_PATH_FILE_NAME;
78 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_PATH_FILE_NAME;
79
80 public abstract class AbstractToscaConverter implements ToscaConverter {
81
82     @Override
83     public abstract ToscaServiceModel convert(FileContentHandler fileContentHandler) throws IOException;
84
85     protected void handleMetadataFile(Map<String, byte[]> csarFiles) {
86         byte[] bytes = csarFiles.remove(TOSCA_META_PATH_FILE_NAME);
87         if (bytes != null) {
88             csarFiles.put(TOSCA_META_ORIG_PATH_FILE_NAME, bytes);
89         }
90     }
91
92     protected void handleDefintionTemplate(String key, Map<String, byte[]> csarFiles,
93                                            GlobalSubstitutionServiceTemplate gsst) {
94         try {
95             ServiceTemplateReaderService readerService = new ServiceTemplateReaderServiceImpl(csarFiles.get(key));
96             Object nodeTypes = readerService.getNodeTypes();
97             if (nodeTypes instanceof Map) {
98                 Map<String, NodeType> nodeTypeMap = (Map<String, NodeType>) nodeTypes;
99                 gsst.appendNodes(nodeTypeMap);
100             }
101         } catch (YAMLException ye) {
102             throw new CoreException(new ErrorCode.ErrorCodeBuilder()
103                     .withMessage("Invalid YAML content in file " + key)
104                     .withCategory(ErrorCategory.APPLICATION).build(), ye);
105         }
106     }
107
108     protected String getConcreteArtifactFileName(String fileName){
109         int artifactIndex = fileName.indexOf(CsarFileTypes.Artifacts.name());
110         if(artifactIndex < 0){
111             return fileName;
112         }
113
114         int artifactDirectoryIndex =
115                 artifactIndex + CsarFileTypes.Artifacts.name().length() + 1;
116         return fileName.substring(artifactDirectoryIndex);
117     }
118
119     protected void updateToscaServiceModel(ToscaServiceModel toscaServiceModel,
120                                            Map<String, ServiceTemplate> serviceTemplates,
121                                            FileContentHandler externalFilesHandler,
122                                            GlobalSubstitutionServiceTemplate globalSubstitutionServiceTemplate,
123                                            Map<String, byte[]> csarFiles, String entryDefinitionServiceTemplateName) {
124         Collection<ServiceTemplate> globalServiceTemplates =
125                 GlobalTypesGenerator.getGlobalTypesServiceTemplate(OnboardingTypesEnum.CSAR).values();
126         addGlobalServiceTemplates(globalServiceTemplates, serviceTemplates);
127         toscaServiceModel.setServiceTemplates(serviceTemplates);
128         toscaServiceModel.setEntryDefinitionServiceTemplate(entryDefinitionServiceTemplateName);
129         externalFilesHandler.addFile(TOSCA_META_ORIG_PATH_FILE_NAME,
130                 csarFiles.get(TOSCA_META_ORIG_PATH_FILE_NAME));
131         toscaServiceModel.setArtifactFiles(externalFilesHandler);
132
133         if(MapUtils.isNotEmpty(globalSubstitutionServiceTemplate.getNode_types())) {
134             serviceTemplates
135                     .put(GLOBAL_SUBSTITUTION_SERVICE_FILE_NAME, globalSubstitutionServiceTemplate);
136         }
137     }
138
139     private void addGlobalServiceTemplates(Collection<ServiceTemplate> globalServiceTemplates,
140                                            Map<String, ServiceTemplate> serviceTemplates) {
141         for (ServiceTemplate serviceTemplate : globalServiceTemplates) {
142             serviceTemplates.put(ToscaUtil.getServiceTemplateFileName(serviceTemplate), serviceTemplate);
143         }
144     }
145
146     protected void handleServiceTemplate(String serviceTemplateName,
147                                          String fileName, Map<String, byte[]> csarFiles,
148                                          Map<String, ServiceTemplate> serviceTemplates) {
149         Optional<ServiceTemplate> serviceTemplate =
150                 getServiceTemplateFromCsar(fileName, csarFiles);
151         serviceTemplate.ifPresent(
152                 serviceTemplateValue -> addServiceTemplate(serviceTemplateName, serviceTemplateValue,
153                         serviceTemplates));
154     }
155
156     private void addServiceTemplate(String serviceTemplateName,
157                                     ServiceTemplate serviceTemplate,
158                                     Map<String, ServiceTemplate> serviceTemplates) {
159         serviceTemplates.put(serviceTemplateName, serviceTemplate);
160     }
161
162     private Optional<ServiceTemplate> getServiceTemplateFromCsar(String fileName,
163                                                                  Map<String, byte[]> csarFiles) {
164         byte[] fileContent = csarFiles.get(fileName);
165         ServiceTemplate serviceTemplate = convertServiceTemplate(fileName, fileContent);
166
167         return Optional.of(serviceTemplate);
168     }
169
170     private ServiceTemplate convertServiceTemplate(String serviceTemplateName,
171                                                    byte[] fileContent) {
172         ServiceTemplate serviceTemplate = new ServiceTemplate();
173         try {
174             ServiceTemplateReaderService readerService =
175                     new ServiceTemplateReaderServiceImpl(fileContent);
176             convertMetadata(serviceTemplateName, serviceTemplate, readerService);
177             convertToscaVersion(serviceTemplate, readerService);
178             convertImports(serviceTemplate);
179             convertNodeTypes(serviceTemplate, readerService);
180             convertTopologyTemplate(serviceTemplate, readerService);
181
182         } catch (YAMLException ye) {
183             throw new CoreException(new ErrorCode.ErrorCodeBuilder()
184                     .withMessage("Invalid YAML content in file" + serviceTemplateName)
185                     .withCategory(ErrorCategory.APPLICATION).build(), ye);
186         }
187
188
189         return serviceTemplate;
190     }
191
192     private void convertToscaVersion(ServiceTemplate serviceTemplate,
193                                      ServiceTemplateReaderService readerService) {
194         Object toscaVersion = readerService.getToscaVersion();
195         serviceTemplate.setTosca_definitions_version((String) toscaVersion);
196     }
197
198     private void convertImports(ServiceTemplate serviceTemplate) {
199         serviceTemplate.setImports(new ArrayList<>());
200         serviceTemplate.getImports()
201                 .add(createImportMap(openecompHeatIndex, HEAT_INDEX_IMPORT_FILE));
202         serviceTemplate.getImports().add(createImportMap(ONAP_INDEX, ONAP_INDEX_IMPORT_FILE));
203         serviceTemplate.getImports().add(createImportMap(globalSubstitution, globalStName));
204
205     }
206
207     private Map<String, Import> createImportMap(String key, String fileName) {
208         Map<String, Import> importMap = new HashMap<>();
209         Import anImport = new Import();
210         anImport.setFile(fileName);
211         importMap.put(key, anImport);
212
213         return importMap;
214     }
215
216     private void convertMetadata(String serviceTemplateName,
217                                  ServiceTemplate serviceTemplate,
218                                  ServiceTemplateReaderService readerService) {
219         Map<String, Object> metadataToConvert = (Map<String, Object>) readerService.getMetadata();
220         Map<String, String> finalMetadata = new HashMap<>();
221
222         if (MapUtils.isNotEmpty(metadataToConvert)) {
223             for (Map.Entry<String, Object> metadataEntry : metadataToConvert.entrySet()) {
224                 if (Objects.isNull(metadataEntry.getValue()) ||
225                         !(metadataEntry.getValue() instanceof String)) {
226                     continue;
227                 }
228                 finalMetadata.put(metadataEntry.getKey(), (String) metadataEntry.getValue());
229             }
230         }
231
232         finalMetadata.put("template_name", getTemplateNameFromStName(serviceTemplateName));
233         serviceTemplate.setMetadata(finalMetadata);
234     }
235
236     private void convertNodeTypes(ServiceTemplate serviceTemplate, ServiceTemplateReaderService readerService) {
237         Map<String, Object> nodeTypes = readerService.getNodeTypes();
238         if (MapUtils.isEmpty(nodeTypes)) {
239             return;
240         }
241
242         for (Map.Entry<String, Object> nodeTypeEntry : nodeTypes.entrySet()) {
243             Optional<NodeType> nodeType = ToscaConverterUtil
244                     .createObjectFromClass(nodeTypeEntry.getKey(), nodeTypeEntry.getValue(),
245                             NodeType.class);
246
247             nodeType.ifPresent(nodeTypeValue -> DataModelUtil
248                     .addNodeType(serviceTemplate, nodeTypeEntry.getKey(), nodeTypeValue));
249         }
250     }
251
252     private void convertTopologyTemplate(ServiceTemplate serviceTemplate,
253                                          ServiceTemplateReaderService readerService) {
254
255         convertInputs(serviceTemplate, readerService);
256         convertNodeTemplates(serviceTemplate, readerService);
257         convertOutputs(serviceTemplate, readerService);
258         convertSubstitutionMappings(serviceTemplate, readerService);
259     }
260
261     private void convertInputs(ServiceTemplate serviceTemplate,
262                                ServiceTemplateReaderService readerService) {
263         Map<String, Object> inputs = readerService.getInputs();
264         addInputsOrOutputsToServiceTemplate(serviceTemplate, inputs, Constants.inputs);
265     }
266
267     private void convertOutputs(ServiceTemplate serviceTemplate,
268                                 ServiceTemplateReaderService readerService) {
269         Map<String, Object> outputs = readerService.getOutputs();
270         addInputsOrOutputsToServiceTemplate(serviceTemplate, outputs, Constants.outputs);
271     }
272
273     private void addInputsOrOutputsToServiceTemplate(ServiceTemplate serviceTemplate,
274                                                      Map<String, Object> mapToConvert,
275                                                      String inputsOrOutputs) {
276         if (MapUtils.isEmpty(mapToConvert)) {
277             return;
278         }
279
280         for (Map.Entry<String, Object> entry : mapToConvert.entrySet()) {
281             Optional<ParameterDefinition> parameterDefinition =
282                     ToscaConverterUtil.createObjectFromClass(
283                             entry.getKey(), entry.getValue(), ParameterDefinition.class);
284
285             parameterDefinition.ifPresent(parameterDefinitionValue -> {
286                 Optional<Object> defaultValue =
287                         ToscaConverterUtil.getDefaultValue(entry.getValue(), parameterDefinition.get());
288                 defaultValue.ifPresent(parameterDefinitionValue::set_default);
289                 addToServiceTemplateAccordingToSection(
290                         serviceTemplate, inputsOrOutputs, entry.getKey(), parameterDefinition.get());
291             });
292         }
293     }
294
295     private void addToServiceTemplateAccordingToSection(ServiceTemplate serviceTemplate,
296                                                         String inputsOrOutputs,
297                                                         String parameterId,
298                                                         ParameterDefinition parameterDefinition) {
299         if (inputsOrOutputs.equals(inputs)) {
300             DataModelUtil
301                     .addInputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
302         } else if (inputsOrOutputs.equals(outputs)) {
303             DataModelUtil
304                     .addOutputParameterToTopologyTemplate(serviceTemplate, parameterId, parameterDefinition);
305         }
306     }
307
308     private void convertNodeTemplates(ServiceTemplate serviceTemplate,
309                                       ServiceTemplateReaderService readerService) {
310         Map<String, Object> nodeTemplates = readerService.getNodeTemplates();
311         if (MapUtils.isEmpty(nodeTemplates)) {
312             return;
313         }
314
315         for (Map.Entry<String, Object> nodeTemplateEntry : nodeTemplates.entrySet()) {
316             NodeTemplate nodeTemplate = convertNodeTemplate(nodeTemplateEntry.getValue());
317             DataModelUtil.addNodeTemplate(serviceTemplate, nodeTemplateEntry.getKey(), nodeTemplate);
318         }
319     }
320
321     private void convertSubstitutionMappings(ServiceTemplate serviceTemplate,
322                                              ServiceTemplateReaderService readerService) {
323         Map<String, Object> substitutionMappings = readerService.getSubstitutionMappings();
324         if (MapUtils.isEmpty(substitutionMappings)) {
325             return;
326         }
327         SubstitutionMapping substitutionMapping = convertSubstitutionMappings(substitutionMappings);
328         DataModelUtil.addSubstitutionMapping(serviceTemplate, substitutionMapping);
329     }
330
331     private SubstitutionMapping convertSubstitutionMappings(
332             Map<String, Object> substitutionMappings) {
333         SubstitutionMapping substitutionMapping = new SubstitutionMapping();
334
335         substitutionMapping.setNode_type((String) substitutionMappings.get(nodeType));
336         substitutionMapping.setCapabilities(
337                 convertSubstitutionMappingsSections(capabilities, substitutionMappings.get(capabilities)));
338         substitutionMapping.setRequirements(
339                 convertSubstitutionMappingsSections(requirements, substitutionMappings.get(requirements)));
340
341         return substitutionMapping;
342     }
343
344     private Map<String, List<String>> convertSubstitutionMappingsSections(String sectionName,
345                                                                           Object sectionToConvert) {
346
347         if (Objects.isNull(sectionToConvert)) {
348             return null;
349         }
350
351         if (!(sectionToConvert instanceof Map)) {
352             throw new CoreException(
353                     new SubstitutionMappingsConverterErrorBuilder(
354                             sectionName, sectionToConvert.getClass().getSimpleName()).build());
355         }
356
357         return convertSection(sectionToConvert);
358     }
359
360     private Map<String, List<String>> convertSection(Object sectionToConvert) {
361
362         Map<String, Object> sectionAsMap = (Map<String, Object>) sectionToConvert;
363         Map<String, List<String>> convertedSection = new HashMap<>();
364
365         if (MapUtils.isEmpty(sectionAsMap)) {
366             return null;
367         }
368
369         for (Map.Entry<String, Object> entry : sectionAsMap.entrySet()) {
370             if (entry.getValue() instanceof List) {
371                 convertedSection.put(entry.getKey(), (List<String>) entry.getValue());
372             }
373         }
374
375         return convertedSection;
376     }
377
378     protected  CsarFileTypes getFileType(String fileName){
379         if (isMainServiceTemplate(fileName)) {
380             return CsarFileTypes.mainServiceTemplate;
381         } else if (isGlobalServiceTemplate(fileName)) {
382             return CsarFileTypes.globalServiceTemplate;
383         } else if (isDefinitions(fileName)) {
384             return CsarFileTypes.definitionsFile;
385         } else if (isMetadataFile(fileName)) {
386             return CsarFileTypes.toscaMetadata;
387         }
388         return CsarFileTypes.externalFile;
389     }
390
391     private NodeTemplate convertNodeTemplate(Object candidateNodeTemplate) {
392         NodeTemplate nodeTemplate = new NodeTemplate();
393
394         Map<String, Object> nodeTemplateAsMap = (Map<String, Object>) candidateNodeTemplate;
395         nodeTemplate.setArtifacts((Map<String, ArtifactDefinition>) nodeTemplateAsMap.get("artifacts"));
396         nodeTemplate.setAttributes((Map<String, Object>) nodeTemplateAsMap.get("attributes"));
397         nodeTemplate.setCopy((String) nodeTemplateAsMap.get("copy"));
398         nodeTemplate.setDescription((String) nodeTemplateAsMap.get("description"));
399         nodeTemplate.setDirectives((List<String>) nodeTemplateAsMap.get("directives"));
400         nodeTemplate.setInterfaces(
401                 (Map<String, Object>) nodeTemplateAsMap.get("interfaces"));
402         nodeTemplate.setNode_filter((NodeFilter) nodeTemplateAsMap.get("node_filter"));
403         nodeTemplate.setProperties((Map<String, Object>) nodeTemplateAsMap.get("properties"));
404         nodeTemplate.setRequirements(
405                 (List<Map<String, RequirementAssignment>>) nodeTemplateAsMap.get("requirements"));
406         nodeTemplate.setType((String) nodeTemplateAsMap.get("type"));
407         nodeTemplate.setCapabilities(
408                 convertCapabilities((Map<String, Object>) nodeTemplateAsMap.get("capabilities")));
409
410         return nodeTemplate;
411     }
412
413     private Map<String, CapabilityAssignment> convertCapabilities(Map<String, Object> capabilities) {
414         if (MapUtils.isEmpty(capabilities)) {
415             return null;
416         }
417
418         Map<String, CapabilityAssignment> convertedCapabilities = new HashMap<>();
419         for (Map.Entry<String, Object> capabilityAssignmentEntry : capabilities.entrySet()) {
420             Optional<CapabilityAssignment> capabilityAssignment = ToscaConverterUtil.createObjectFromClass
421                     (capabilityAssignmentEntry.getKey(), capabilityAssignmentEntry.getValue(),
422                             CapabilityAssignment.class);
423
424             capabilityAssignment.ifPresent(capabilityAssignmentValue ->
425                     convertedCapabilities.put(capabilityAssignmentEntry.getKey(), capabilityAssignmentValue));
426
427         }
428         return convertedCapabilities;
429     }
430
431
432     protected boolean isMainServiceTemplate(String fileName) {
433         return fileName.endsWith(mainStName);
434     }
435
436     protected boolean isMetadataFile(String fileName) {
437         return fileName.equals(TOSCA_META_PATH_FILE_NAME);
438     }
439
440     protected boolean isGlobalServiceTemplate(String fileName) {
441         return fileName.endsWith(globalStName);
442     }
443
444     protected boolean isDefinitions(String fileName) {
445         return fileName.startsWith(definitionsDir);
446     }
447
448     private String getTemplateNameFromStName(String serviceTemplateName) {
449         String fileNameWithoutDirectories = getFileNameWithoutDirectories(serviceTemplateName);
450         return fileNameWithoutDirectories.split("ServiceTemplate")[0];
451     }
452
453     private String getFileNameWithoutDirectories(String serviceTemplateName) {
454         String fileNameWithoutDirectories;
455         if (serviceTemplateName.contains("/")) {
456             String[] split = serviceTemplateName.split("/");
457             fileNameWithoutDirectories = split[split.length - 1];
458         } else if (serviceTemplateName.contains(File.separator)) {
459             String[] split = serviceTemplateName.split(Pattern.quote(File.separator));
460             fileNameWithoutDirectories = split[split.length - 1];
461         } else {
462             fileNameWithoutDirectories = serviceTemplateName;
463         }
464         return fileNameWithoutDirectories;
465     }
466 }