Reformat catalog-be-plugins
[sdc.git] / catalog-be-plugins / etsi-nfv-nsd-csar-plugin / src / main / java / org / openecomp / sdc / be / plugins / etsi / nfv / nsd / generator / VnfDescriptorGeneratorImpl.java
1  
2 /*
3  * ============LICENSE_START=======================================================
4  *  Copyright (C) 2020 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  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.be.plugins.etsi.nfv.nsd.generator;
21
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.nio.charset.StandardCharsets;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Optional;
31 import java.util.stream.Collectors;
32 import org.apache.commons.collections.MapUtils;
33 import org.apache.commons.io.FilenameUtils;
34 import org.apache.commons.io.IOUtils;
35 import org.onap.sdc.tosca.services.YamlUtil;
36 import org.openecomp.core.utilities.file.FileContentHandler;
37 import org.openecomp.core.utilities.file.FileUtils;
38 import org.openecomp.sdc.be.model.ArtifactDefinition;
39 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.builder.NsdToscaMetadataBuilder;
40 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.exception.VnfDescriptorException;
41 import org.openecomp.sdc.be.plugins.etsi.nfv.nsd.model.VnfDescriptor;
42 import org.openecomp.sdc.common.zip.exception.ZipException;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.springframework.stereotype.Component;
46 import org.yaml.snakeyaml.Yaml;
47
48 /**
49  * Implementation of a VNF Descriptor Generator
50  */
51 @Component("vnfPackageGenerator")
52 public class VnfDescriptorGeneratorImpl implements VnfDescriptorGenerator {
53
54     private static final Logger LOGGER = LoggerFactory.getLogger(VnfDescriptorGeneratorImpl.class);
55     private static final String SPACE_REGEX = "\\s+";
56     private static final String CSAR = "csar";
57     private static final String COLON = ":";
58     private static final String EMPTY_STRING = "";
59     private static final String SLASH = "/";
60     private static final String DEFINITIONS_DIRECTORY = "Definitions";
61     private static final String TOSCA_META_PATH = "TOSCA-Metadata/TOSCA.meta";
62
63     private static boolean isACsarArtifact(final ArtifactDefinition definition) {
64         return definition.getPayloadData() != null && definition.getArtifactName() != null && CSAR
65             .equalsIgnoreCase(FilenameUtils.getExtension(definition.getArtifactName()));
66     }
67
68     public Optional<VnfDescriptor> generate(final String name, final ArtifactDefinition onboardedPackageArtifact) throws VnfDescriptorException {
69         if (!isACsarArtifact(onboardedPackageArtifact)) {
70             return Optional.empty();
71         }
72         final FileContentHandler fileContentHandler;
73         try {
74             fileContentHandler = FileUtils.getFileContentMapFromZip(onboardedPackageArtifact.getPayloadData());
75         } catch (final ZipException e) {
76             final String errorMsg = String.format("Could not unzip artifact '%s' content", onboardedPackageArtifact.getArtifactName());
77             throw new VnfDescriptorException(errorMsg, e);
78         }
79         if (MapUtils.isEmpty(fileContentHandler.getFiles())) {
80             return Optional.empty();
81         }
82         final String mainDefinitionFile;
83         try {
84             mainDefinitionFile = getMainFilePathFromMetaFile(fileContentHandler).orElse(null);
85         } catch (final IOException e) {
86             final String errorMsg = String.format("Could not read main definition file of artifact '%s'", onboardedPackageArtifact.getArtifactName());
87             throw new VnfDescriptorException(errorMsg, e);
88         }
89         LOGGER.debug("found main file: {}", mainDefinitionFile);
90         if (mainDefinitionFile == null) {
91             return Optional.empty();
92         }
93         final VnfDescriptor vnfDescriptor = new VnfDescriptor();
94         vnfDescriptor.setName(name);
95         final String vnfdFileName = FilenameUtils.getName(mainDefinitionFile);
96         vnfDescriptor.setVnfdFileName(vnfdFileName);
97         vnfDescriptor.setDefinitionFiles(getFiles(fileContentHandler, mainDefinitionFile));
98         vnfDescriptor.setNodeType(getNodeType(getFileContent(fileContentHandler, mainDefinitionFile)));
99         return Optional.of(vnfDescriptor);
100     }
101
102     private Map<String, byte[]> getFiles(final FileContentHandler fileContentHandler, final String filePath) {
103         final Map<String, byte[]> files = new HashMap<>();
104         final byte[] fileContent = fileContentHandler.getFileContent(filePath);
105         if (fileContent != null) {
106             final String mainYmlFile = new String(fileContent);
107             LOGGER.debug("file content: {}", mainYmlFile);
108             files.put(appendDefinitionDirPath(filePath.substring(filePath.lastIndexOf(SLASH) + 1)), getVnfdWithoutTopologyTemplate(fileContent));
109             final List<Object> imports = getImportFilesPath(mainYmlFile);
110             LOGGER.info("found imports {}", imports);
111             for (final Object importObject : imports) {
112                 if (importObject != null) {
113                     final String importFilename = importObject.toString();
114                     final String importFileFullPath = appendDefinitionDirPath(importFilename);
115                     final byte[] importFileContent = fileContentHandler.getFileContent(importFileFullPath);
116                     files.put(appendDefinitionDirPath(importFilename), importFileContent);
117                 }
118             }
119         }
120         return files;
121     }
122
123     private String getFileContent(final FileContentHandler fileContentHandler, final String filePath) {
124         final byte[] fileContent = fileContentHandler.getFileContent(filePath);
125         if (fileContent != null) {
126             return new String(fileContent);
127         }
128         return null;
129     }
130
131     private Optional<String> getMainFilePathFromMetaFile(final FileContentHandler fileContentHandler) throws IOException {
132         final Map<String, String> metaFileContent = getMetaFileContent(fileContentHandler);
133         final String mainFile = metaFileContent.get(NsdToscaMetadataBuilder.ENTRY_DEFINITIONS);
134         if (mainFile != null) {
135             return Optional.of(mainFile.replaceAll(SPACE_REGEX, EMPTY_STRING));
136         }
137         LOGGER.error("{} entry not found in {}", NsdToscaMetadataBuilder.ENTRY_DEFINITIONS, TOSCA_META_PATH);
138         return Optional.empty();
139     }
140
141     private Map<String, String> getMetaFileContent(final FileContentHandler fileContentHandler) throws IOException {
142         final InputStream inputStream = fileContentHandler.getFileContentAsStream(TOSCA_META_PATH);
143         if (inputStream == null) {
144             throw new FileNotFoundException("Unable find " + TOSCA_META_PATH + " file");
145         }
146         final List<String> lines = IOUtils.readLines(inputStream, StandardCharsets.UTF_8);
147         return lines.stream().map(str -> str.split(COLON)).collect(Collectors.toMap(str -> str[0], str -> str.length > 1 ? str[1] : EMPTY_STRING));
148     }
149
150     private String appendDefinitionDirPath(final String filename) {
151         return DEFINITIONS_DIRECTORY + SLASH + filename;
152     }
153
154     private List<Object> getImportFilesPath(final String mainYmlFile) {
155         final Map<Object, Object> fileContentMap = new YamlUtil().yamlToObject(mainYmlFile, Map.class);
156         final Object importsObject = fileContentMap.get("imports");
157         if (importsObject instanceof List) {
158             return (List<Object>) importsObject;
159         }
160         return Collections.emptyList();
161     }
162
163     private byte[] getVnfdWithoutTopologyTemplate(final byte[] vnfdFileContent) {
164         final Yaml yaml = new Yaml();
165         final Map<String, Object> toscaFileContent = (Map<String, Object>) yaml.load(new String(vnfdFileContent));
166         toscaFileContent.remove("topology_template");
167         return yaml.dumpAsMap(toscaFileContent).getBytes();
168     }
169
170     private String getNodeType(final String mainYmlFile) {
171         final Map<Object, Object> fileContentMap = new YamlUtil().yamlToObject(mainYmlFile, Map.class);
172         final Object nodeTypesObject = fileContentMap.get("node_types");
173         if (nodeTypesObject instanceof Map && ((Map<String, Object>) nodeTypesObject).size() == 1) {
174             return ((Map<String, Object>) nodeTypesObject).keySet().iterator().next();
175         }
176         return null;
177     }
178 }