Create plugin point for csar generation
[sdc.git] / catalog-be-plugins / etsi-nfv-nsd-csar-plugin / src / main / java / org / openecomp / sdc / be / plugins / etsi / nfv / nsd / generator / NsDescriptorGeneratorImpl.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2020 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        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.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19 package org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator;
20
21 import com.google.common.collect.ImmutableMap;
22 import fj.data.Either;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.Optional;
32 import java.util.stream.Collectors;
33 import org.apache.commons.collections4.CollectionUtils;
34 import org.apache.commons.collections4.MapUtils;
35 import org.openecomp.sdc.be.config.ConfigurationManager;
36 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
37 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
38 import org.openecomp.sdc.be.model.Component;
39 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.exception.NsdException;
40 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.Nsd;
41 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.VnfDescriptor;
42 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.tosca.yaml.ToscaTemplateYamlGenerator;
43 import org.openecomp.sdc.be.tosca.ToscaError;
44 import org.openecomp.sdc.be.tosca.ToscaExportHandler;
45 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
46 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
47 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
48 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
49 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraint;
50 import org.openecomp.sdc.be.tosca.model.ToscaPropertyConstraintValidValues;
51 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
52 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
53 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
54 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57 import org.springframework.beans.factory.ObjectProvider;
58 import org.springframework.beans.factory.config.BeanDefinition;
59 import org.springframework.context.annotation.Scope;
60
61 @org.springframework.stereotype.Component("nsDescriptorGenerator")
62 @Scope(BeanDefinition.SCOPE_PROTOTYPE)
63 public class NsDescriptorGeneratorImpl implements NsDescriptorGenerator {
64
65     private static final Logger LOGGER = LoggerFactory.getLogger(NsDescriptorGeneratorImpl.class);
66     private static final String TOSCA_VERSION = "tosca_simple_yaml_1_1";
67     private static final String NS_TOSCA_TYPE = "tosca.nodes.nfv.NS";
68     private static final List<Map<String, Map<String, String>>> DEFAULT_IMPORTS = ConfigurationManager.getConfigurationManager().getConfiguration()
69         .getDefaultImports();
70     private static final List<String> PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TYPE = Arrays
71         .asList("cds_model_name", "cds_model_version", "skip_post_instantiation_configuration", "controller_actor");
72     private static final List<String> ETSI_SOL_NSD_NS_NODE_TYPE_PROPERTIES = Arrays
73         .asList("descriptor_id", "designer", "version", "name", "invariant_id", "flavour_id", "ns_profile", "service_availability_level");
74     private static final List<String> PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TEMPLATE = Arrays
75         .asList("nf_function", "nf_role", "nf_naming_code", "nf_type", "nf_naming", "availability_zone_max_count", "min_instances", "max_instances",
76             "multi_stage_design", "sdnc_model_name", "sdnc_model_version", "sdnc_artifact_name", "skip_post_instantiation_configuration",
77             "controller_actor");
78     private final ToscaExportHandler toscaExportHandler;
79     private final ObjectProvider<ToscaTemplateYamlGenerator> toscaTemplateYamlGeneratorProvider;
80
81     public NsDescriptorGeneratorImpl(final ToscaExportHandler toscaExportHandler,
82                                      final ObjectProvider<ToscaTemplateYamlGenerator> toscaTemplateYamlGeneratorProvider) {
83         this.toscaExportHandler = toscaExportHandler;
84         this.toscaTemplateYamlGeneratorProvider = toscaTemplateYamlGeneratorProvider;
85     }
86
87     public Optional<Nsd> generate(final Component component, final List<VnfDescriptor> vnfDescriptorList) throws NsdException {
88         if (!ComponentTypeEnum.SERVICE.equals(component.getComponentType())) {
89             return Optional.empty();
90         }
91         final ToscaTemplate toscaTemplate = createNetworkServiceDescriptor(component, vnfDescriptorList);
92         final ToscaNodeType nsNodeType = toscaTemplate.getNode_types().values().stream()
93             .filter(toscaNodeType -> NS_TOSCA_TYPE.equals(toscaNodeType.getDerived_from())).findFirst().orElse(null);
94         if (nsNodeType == null) {
95             return Optional.empty();
96         }
97         return Optional.of(buildNsd(toscaTemplate, nsNodeType));
98     }
99
100     private Nsd buildNsd(final ToscaTemplate toscaTemplate, final ToscaNodeType nsNodeType) {
101         final Nsd nsd = new Nsd();
102         nsd.setDesigner(getProperty(nsNodeType, Nsd.DESIGNER_PROPERTY));
103         nsd.setVersion(getProperty(nsNodeType, Nsd.VERSION_PROPERTY));
104         nsd.setName(getProperty(nsNodeType, Nsd.NAME_PROPERTY));
105         nsd.setInvariantId(getProperty(nsNodeType, Nsd.INVARIANT_ID_PROPERTY));
106         final ToscaTemplateYamlGenerator yamlParserProvider = toscaTemplateYamlGeneratorProvider.getObject(toscaTemplate);
107         final byte[] contents = yamlParserProvider.parseToYamlString().getBytes();
108         nsd.setContents(contents);
109         final List<String> interfaceImplementations = getInterfaceImplementations(toscaTemplate);
110         nsd.setArtifactReferences(interfaceImplementations);
111         return nsd;
112     }
113
114     private List<String> getInterfaceImplementations(final ToscaTemplate template) {
115         if (template.getTopology_template().getNode_templates() == null) {
116             return Collections.emptyList();
117         }
118         final List<String> interfaceImplementations = new ArrayList<>();
119         final Collection<ToscaNodeTemplate> nodeTemplates = template.getTopology_template().getNode_templates().values();
120         nodeTemplates.stream().filter(toscaNodeTemplate -> toscaNodeTemplate.getInterfaces() != null).forEach(
121             toscaNodeTemplate -> toscaNodeTemplate.getInterfaces().values()
122                 .forEach(interfaceInstance -> interfaceImplementations.addAll(getInterfaceImplementations(interfaceInstance))));
123         return interfaceImplementations;
124     }
125
126     private Collection<String> getInterfaceImplementations(final Object interfaceInstance) {
127         final Collection<String> interfaceImplementations = new ArrayList<>();
128         if (interfaceInstance instanceof Map) {
129             for (final Object value : ((Map<?, ?>) interfaceInstance).values()) {
130                 if (value instanceof Map && ((Map<?, ?>) value).get("implementation") != null) {
131                     interfaceImplementations.add(((Map<?, ?>) value).get("implementation").toString());
132                 }
133             }
134         }
135         return interfaceImplementations;
136     }
137
138     private String getProperty(final ToscaNodeType nodeType, final String propertyName) {
139         final ToscaProperty toscaProperty = nodeType.getProperties().get(propertyName);
140         final String errorMsg = String.format("Property '%s' must be defined and must have a valid values constraint", propertyName);
141         final String returnValueOnError = "unknown";
142         if (toscaProperty == null || CollectionUtils.isEmpty(toscaProperty.getConstraints())) {
143             LOGGER.error(errorMsg);
144             return returnValueOnError;
145         }
146         final ToscaPropertyConstraint toscaPropertyConstraint = toscaProperty.getConstraints().get(0);
147         if (ConstraintType.VALID_VALUES != toscaPropertyConstraint.getConstraintType()) {
148             LOGGER.error(errorMsg);
149             return returnValueOnError;
150         }
151         final ToscaPropertyConstraintValidValues validValuesConstraint = (ToscaPropertyConstraintValidValues) toscaPropertyConstraint;
152         final List<Object> validValues = validValuesConstraint.getValidValues();
153         if (CollectionUtils.isEmpty(validValues)) {
154             LOGGER.error(errorMsg);
155             return returnValueOnError;
156         }
157         return String.valueOf(validValues.get(0));
158     }
159
160     private ToscaTemplate createNetworkServiceDescriptor(final Component component, final List<VnfDescriptor> vnfDescriptorList) throws NsdException {
161         final ToscaTemplate componentToscaTemplate = parseToToscaTemplate(component);
162         final ToscaTemplate componentToscaTemplateInterface = exportComponentInterfaceAsToscaTemplate(component);
163         final Entry<String, ToscaNodeType> firstNodeTypeEntry = componentToscaTemplateInterface.getNode_types().entrySet().stream().findFirst()
164             .orElse(null);
165         if (firstNodeTypeEntry == null) {
166             throw new NsdException("Could not find abstract Service type");
167         }
168         final String nsNodeTypeName = firstNodeTypeEntry.getKey();
169         final ToscaNodeType nsNodeType = firstNodeTypeEntry.getValue();
170         final Map<String, ToscaNodeType> nodeTypeMap = new HashMap<>();
171         nodeTypeMap.put(nsNodeTypeName, createEtsiSolNsNodeType(nsNodeType, componentToscaTemplate));
172         if (componentToscaTemplate.getNode_types() == null) {
173             componentToscaTemplate.setNode_types(nodeTypeMap);
174         } else {
175             componentToscaTemplate.getNode_types().putAll(nodeTypeMap);
176         }
177         handleNodeTemplates(componentToscaTemplate);
178         removeOnapAndEtsiNsdPropertiesFromInputs(componentToscaTemplate);
179         handleSubstitutionMappings(componentToscaTemplate, nsNodeTypeName);
180         final Map<String, ToscaNodeTemplate> nodeTemplates = new HashMap<>();
181         nodeTemplates.put(nsNodeTypeName,
182             createNodeTemplateForNsNodeType(nsNodeTypeName, componentToscaTemplateInterface.getNode_types().get(nsNodeTypeName)));
183         if (componentToscaTemplate.getTopology_template().getNode_templates() == null) {
184             componentToscaTemplate.getTopology_template().setNode_templates(nodeTemplates);
185         } else {
186             setNodeTemplateTypesForVnfs(componentToscaTemplate, vnfDescriptorList);
187             componentToscaTemplate.getTopology_template().getNode_templates().putAll(nodeTemplates);
188         }
189         removeOnapMetaData(componentToscaTemplate);
190         setDefaultImportsForEtsiSolNsNsd(componentToscaTemplate, vnfDescriptorList);
191         return componentToscaTemplate;
192     }
193
194     private void handleSubstitutionMappings(final ToscaTemplate componentToscaTemplate, final String nsNodeTypeName) {
195         final SubstitutionMapping substitutionMapping = new SubstitutionMapping();
196         substitutionMapping.setNode_type(nsNodeTypeName);
197         final SubstitutionMapping onapSubstitutionMapping = componentToscaTemplate.getTopology_template().getSubstitution_mappings();
198         if (onapSubstitutionMapping != null && onapSubstitutionMapping.getRequirements() != null) {
199             substitutionMapping.setRequirements(adjustRequirementNamesToMatchVnfd(onapSubstitutionMapping.getRequirements()));
200         }
201         componentToscaTemplate.getTopology_template().setSubstitution_mappings(substitutionMapping);
202     }
203
204     private Map<String, String[]> adjustRequirementNamesToMatchVnfd(final Map<String, String[]> requirements) {
205         for (final Map.Entry<String, String[]> entry : requirements.entrySet()) {
206             try {
207                 final String[] adjustedValue = {entry.getValue()[0], entry.getValue()[1].substring(entry.getValue()[1].lastIndexOf('.') + 1)};
208                 entry.setValue(adjustedValue);
209             } catch (final ArrayIndexOutOfBoundsException exception) {
210                 LOGGER.error("Malformed requirement: {}", entry);
211             }
212         }
213         return requirements;
214     }
215
216     private void setNodeTemplateTypesForVnfs(final ToscaTemplate template, final List<VnfDescriptor> vnfDescriptorList) {
217         if (CollectionUtils.isEmpty(vnfDescriptorList)) {
218             return;
219         }
220         final Map<String, ToscaNodeTemplate> nodeTemplateMap = template.getTopology_template().getNode_templates();
221         if (MapUtils.isEmpty(nodeTemplateMap)) {
222             return;
223         }
224         nodeTemplateMap.forEach(
225             (key, toscaNodeTemplate) -> vnfDescriptorList.stream().filter(vnfDescriptor -> key.equals(vnfDescriptor.getName())).findFirst()
226                 .ifPresent(vnfDescriptor -> toscaNodeTemplate.setType(vnfDescriptor.getNodeType())));
227     }
228
229     private void handleNodeTemplates(final ToscaTemplate template) {
230         final Map<String, ToscaNodeTemplate> nodeTemplateMap = template.getTopology_template().getNode_templates();
231         if (MapUtils.isEmpty(nodeTemplateMap)) {
232             return;
233         }
234         for (final Entry<String, ToscaNodeTemplate> nodeTemplate : nodeTemplateMap.entrySet()) {
235             setPropertiesForNodeTemplate(nodeTemplate);
236             setRequirementsForNodeTemplate(nodeTemplate);
237             removeCapabilitiesFromNodeTemplate(nodeTemplate);
238         }
239     }
240
241     private void setPropertiesForNodeTemplate(final Entry<String, ToscaNodeTemplate> nodeTemplate) {
242         final Map<String, Object> propertyMap = nodeTemplate.getValue().getProperties();
243         if (MapUtils.isEmpty(propertyMap)) {
244             nodeTemplate.getValue().setProperties(null);
245             return;
246         }
247         final Map<String, Object> editedPropertyMap = new HashMap<>();
248         for (final Entry<String, Object> property : propertyMap.entrySet()) {
249             if (!PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TEMPLATE.contains(property.getKey()) && propertyIsDefinedInNodeType(
250                 property.getKey())) {
251                 editedPropertyMap.put(property.getKey(), property.getValue());
252             }
253         }
254         if (editedPropertyMap.isEmpty()) {
255             nodeTemplate.getValue().setProperties(null);
256         } else {
257             nodeTemplate.getValue().setProperties(editedPropertyMap);
258         }
259     }
260
261     private void setRequirementsForNodeTemplate(final Entry<String, ToscaNodeTemplate> nodeTemplateMap) {
262         final List<Map<String, ToscaTemplateRequirement>> requirementAssignments = nodeTemplateMap.getValue().getRequirements();
263         if (requirementAssignments != null) {
264             final List<Map<String, ToscaTemplateRequirement>> requirementAssignmentsMatchingVnfdRequirements = new ArrayList<>();
265             for (final Map<String, ToscaTemplateRequirement> requirementAssignment : requirementAssignments) {
266                 final Map<String, ToscaTemplateRequirement> requirementAssignmentMatchingVnfd =
267                     requirementAssignment.entrySet().stream()
268                         .collect(Collectors.toMap(entry -> entry.getKey().substring(entry.getKey().lastIndexOf('.') + 1), Map.Entry::getValue));
269                 requirementAssignmentsMatchingVnfdRequirements.add(requirementAssignmentMatchingVnfd);
270             }
271             nodeTemplateMap.getValue().setRequirements(requirementAssignmentsMatchingVnfdRequirements);
272         }
273     }
274
275
276     private void removeCapabilitiesFromNodeTemplate(final Entry<String, ToscaNodeTemplate> nodeTemplate) {
277         nodeTemplate.getValue().setCapabilities(null);
278     }
279
280     private void removeOnapAndEtsiNsdPropertiesFromInputs(final ToscaTemplate template) {
281         final ToscaTopolgyTemplate topologyTemplate = template.getTopology_template();
282         final Map<String, ToscaProperty> inputMap = topologyTemplate.getInputs();
283
284         if (MapUtils.isNotEmpty(inputMap)) {
285             inputMap.entrySet().removeIf(entry -> PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TYPE.contains(entry.getKey())
286                 || ETSI_SOL_NSD_NS_NODE_TYPE_PROPERTIES.contains(entry.getKey()));
287         }
288         if (MapUtils.isEmpty(inputMap)) {
289             topologyTemplate.setInputs(null);
290         }
291     }
292
293     private void removeOnapMetaData(final ToscaTemplate template) {
294         template.setMetadata(null);
295         final Map<String, ToscaNodeTemplate> nodeTemplateMap = template.getTopology_template().getNode_templates();
296         if (MapUtils.isEmpty(nodeTemplateMap)) {
297             return;
298         }
299         nodeTemplateMap.values().forEach(toscaNodeTemplate -> toscaNodeTemplate.setMetadata(null));
300     }
301
302     private void setDefaultImportsForEtsiSolNsNsd(final ToscaTemplate template, final List<VnfDescriptor> vnfDescriptorList) {
303         final List<Map<String, Map<String, String>>> importEntryMap = new ArrayList<>();
304         final Map<String, Map<String, String>> defaultImportEntryMap = generateDefaultImportEntry();
305         if (MapUtils.isNotEmpty(defaultImportEntryMap)) {
306             importEntryMap.add(defaultImportEntryMap);
307         }
308         if (CollectionUtils.isNotEmpty(vnfDescriptorList)) {
309             for (final VnfDescriptor vnfDescriptor : vnfDescriptorList) {
310                 final Map<String, String> vnfImportChildEntry = new HashMap<>();
311                 vnfImportChildEntry.put("file", vnfDescriptor.getVnfdFileName());
312                 final Map<String, Map<String, String>> vnfdImportVnfdEntry = new HashMap<>();
313                 vnfdImportVnfdEntry.put(vnfDescriptor.getName(), vnfImportChildEntry);
314                 importEntryMap.add(vnfdImportVnfdEntry);
315             }
316         }
317         template.setImports(importEntryMap);
318     }
319
320     private Map<String, Map<String, String>> generateDefaultImportEntry() {
321         return Map.of("etsi_nfv_sol001_nsd_types", Map.of("file", "etsi_nfv_sol001_nsd_types.yaml"));
322     }
323
324     private ToscaNodeType createEtsiSolNsNodeType(final ToscaNodeType nsNodeType, final ToscaTemplate componentToscaTemplate) {
325         final ToscaNodeType toscaNodeType = new ToscaNodeType();
326         toscaNodeType.setDerived_from(NS_TOSCA_TYPE);
327         final Map<String, ToscaProperty> propertiesInNsNodeType = nsNodeType.getProperties();
328         for (final Entry<String, ToscaProperty> property : propertiesInNsNodeType.entrySet()) {
329             final ToscaProperty toscaProperty = property.getValue();
330             if (toscaProperty.getDefaultp() != null && ETSI_SOL_NSD_NS_NODE_TYPE_PROPERTIES.contains(property.getKey())) {
331                 final ToscaPropertyConstraintValidValues constraint = new ToscaPropertyConstraintValidValues(
332                     Collections.singletonList(toscaProperty.getDefaultp().toString()));
333                 toscaProperty.setConstraints(Collections.singletonList(constraint));
334             }
335         }
336         propertiesInNsNodeType.entrySet().removeIf(entry -> PROPERTIES_TO_EXCLUDE_FROM_ETSI_SOL_NSD_NS_NODE_TYPE.contains(entry.getKey()));
337         toscaNodeType.setProperties(propertiesInNsNodeType);
338
339         final List<Map<String, ToscaRequirement>> requirementsInNsNodeType = getRequirementsForNsNodeType(nsNodeType.getRequirements(),
340             componentToscaTemplate);
341         if (!requirementsInNsNodeType.isEmpty()) {
342             toscaNodeType.setRequirements(requirementsInNsNodeType);
343         }
344
345         return toscaNodeType;
346     }
347
348     private List<Map<String, ToscaRequirement>> getRequirementsForNsNodeType(final List<Map<String, ToscaRequirement>> requirements,
349                                                                              final ToscaTemplate componentToscaTemplate) {
350         final Map<String, String[]> requirementsInSubstitutionMapping = componentToscaTemplate.getTopology_template().getSubstitution_mappings()
351             .getRequirements();
352         if (requirements == null || MapUtils.isEmpty(requirementsInSubstitutionMapping)) {
353             return Collections.emptyList();
354         }
355         final List<Map<String, ToscaRequirement>> requirementsToAdd = new ArrayList<>();
356         for (final Map<String, ToscaRequirement> requirementMap : requirements) {
357             final Map<String, ToscaRequirement> neededRequirements = requirementMap.entrySet().stream()
358                 .filter(entry -> requirementsInSubstitutionMapping.containsKey(entry.getKey()))
359                 .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
360             if (!neededRequirements.isEmpty()) {
361                 requirementsToAdd.add(neededRequirements);
362             }
363         }
364         return requirementsToAdd;
365
366     }
367
368     private boolean propertyIsDefinedInNodeType(final String propertyName) {
369         // This will achieve what we want for now, but will look into a more generic solution which would involve
370
371         // checking the node_type definition in the VNFD
372         return !propertyName.equals("additional_parameters");
373     }
374
375     private ToscaNodeTemplate createNodeTemplateForNsNodeType(final String nodeType, final ToscaNodeType toscaNodeType) {
376         final ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate();
377         nodeTemplate.setType(nodeType);
378         final Map<String, ToscaProperty> properties = toscaNodeType.getProperties();
379         final Map<String, Object> nodeTemplateProperties = new HashMap<>();
380         for (final Entry<String, ToscaProperty> property : properties.entrySet()) {
381             if (property.getValue().getDefaultp() != null) {
382                 nodeTemplateProperties.put(property.getKey(), property.getValue().getDefaultp());
383             }
384         }
385         if (!nodeTemplateProperties.isEmpty()) {
386             nodeTemplate.setProperties(nodeTemplateProperties);
387         }
388         final Map<String, Object> interfaces = toscaNodeType.getInterfaces();
389         if (interfaces != null) {
390             for (final Entry<String, Object> nodeInterface : interfaces.entrySet()) {
391                 if ("Nslcm".equals(nodeInterface.getKey()) && nodeInterface.getValue() instanceof Map) {
392                     ((Map<?, ?>) nodeInterface.getValue()).remove("type");
393                 }
394             }
395             nodeTemplate.setInterfaces(interfaces);
396         }
397         return nodeTemplate;
398     }
399
400     private ToscaTemplate parseToToscaTemplate(final Component component) throws NsdException {
401         final Either<ToscaTemplate, ToscaError> toscaTemplateRes = toscaExportHandler.convertToToscaTemplate(component, false);
402         if (toscaTemplateRes.isRight()) {
403             String errorMsg = String
404                 .format("Could not parse component '%s' to tosca template. Error '%s'", component.getName(), toscaTemplateRes.right().value().name());
405             throw new NsdException(errorMsg);
406         }
407         return toscaTemplateRes.left().value();
408     }
409
410     private ToscaTemplate exportComponentInterfaceAsToscaTemplate(final Component component) throws NsdException {
411         if (null == DEFAULT_IMPORTS) {
412             throw new NsdException("Could not load default CSAR imports from configuration");
413         }
414         final ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION);
415         toscaTemplate.setImports(new ArrayList<>(DEFAULT_IMPORTS));
416         final Either<ToscaTemplate, ToscaError> toscaTemplateRes = toscaExportHandler
417             .convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, new HashMap<>(), false);
418         if (toscaTemplateRes.isRight()) {
419             throw new NsdException(String.format("Could not create abstract service from component '%s'", component.getName()));
420         }
421         return toscaTemplateRes.left().value();
422     }
423 }