2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019, Nordix Foundation. 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.vendorsoftwareproduct.services.impl.etsi;
23 import static org.openecomp.sdc.tosca.csar.CSARConstants.ARTIFACTS_FOLDER;
24 import static org.openecomp.sdc.tosca.csar.CSARConstants.MAIN_SERVICE_TEMPLATE_MF_FILE_NAME;
25 import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_PNF_METADATA;
26 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ORIG_PATH_FILE_NAME;
27 import static org.openecomp.sdc.tosca.csar.ToscaMetaEntry.ENTRY_DEFINITIONS;
28 import static org.openecomp.sdc.tosca.csar.ToscaMetaEntry.ETSI_ENTRY_CHANGE_LOG;
29 import static org.openecomp.sdc.tosca.csar.ToscaMetaEntry.ETSI_ENTRY_MANIFEST;
30 import static org.openecomp.sdc.tosca.csar.ToscaMetaEntry.TOSCA_META_PATH_FILE_NAME;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.nio.charset.StandardCharsets;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.util.HashMap;
38 import java.util.List;
40 import java.util.Objects;
41 import java.util.Optional;
42 import java.util.stream.Collectors;
43 import org.apache.commons.collections.MapUtils;
44 import org.apache.commons.io.IOUtils;
45 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
46 import org.onap.sdc.tosca.parser.utils.YamlToObjectConverter;
47 import org.onap.sdc.tosca.services.YamlUtil;
48 import org.openecomp.core.utilities.file.FileContentHandler;
49 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
50 import org.openecomp.sdc.logging.api.Logger;
51 import org.openecomp.sdc.logging.api.LoggerFactory;
52 import org.openecomp.sdc.tosca.csar.Manifest;
53 import org.openecomp.sdc.tosca.csar.OnboardingToscaMetadata;
54 import org.openecomp.sdc.tosca.csar.SOL004ManifestOnboarding;
55 import org.openecomp.sdc.tosca.csar.ToscaMetadata;
56 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
58 public class ETSIServiceImpl implements ETSIService {
60 private static final Logger LOGGER = LoggerFactory.getLogger(ETSIServiceImpl.class);
62 private Configuration configuration;
64 public ETSIServiceImpl() throws IOException {
65 final InputStream io = getClass().getClassLoader().getResourceAsStream("nonManoConfig.yaml");
67 throw new IOException("Non Mano configuration not found");
69 final String data = IOUtils.toString(io, StandardCharsets.UTF_8);
70 final YamlToObjectConverter yamlToObjectConverter = new YamlToObjectConverter();
71 configuration = yamlToObjectConverter.convertFromString(data, Configuration.class);
74 public ETSIServiceImpl(Configuration configuration) {
75 this.configuration = configuration;
79 public boolean isSol004WithToscaMetaDirectory(FileContentHandler handler) throws IOException {
80 final Map<String, byte[]> templates = handler.getFiles();
81 return isMetaFilePresent(templates) && hasMetaMandatoryEntries(getMetadata(handler));
85 public Optional<Map<String, Path>> moveNonManoFileToArtifactFolder(final FileContentHandler handler) throws IOException {
86 final Manifest manifest;
88 manifest = getManifest(handler);
89 } catch (final IOException ex) {
90 if (LOGGER.isErrorEnabled()) {
91 LOGGER.error("An error occurred while getting the manifest file", ex);
95 final Path originalManifestPath;
97 originalManifestPath = getOriginalManifestPath(handler);
98 } catch (final IOException ex) {
99 if (LOGGER.isErrorEnabled()) {
100 LOGGER.error("An error occurred while getting the original manifest path", ex);
104 final Map<String, Path> fromToPathMap = new HashMap<>();
105 final Map<String, NonManoType> nonManoKeyFolderMapping = configuration.getNonManoKeyFolderMapping();
106 manifest.getNonManoSources().entrySet().stream()
107 .filter(manifestNonManoSourceEntry -> nonManoKeyFolderMapping.containsKey(manifestNonManoSourceEntry.getKey()))
108 .forEach(manifestNonManoSourceEntry -> {
109 final NonManoType nonManoType = nonManoKeyFolderMapping.get(manifestNonManoSourceEntry.getKey());
110 final List<String> nonManoFileList = manifestNonManoSourceEntry.getValue();
111 final Map<String, Path> actualFromToPathMap = nonManoFileList.stream()
112 .map(nonManoFilePath -> {
113 final Path normalizedFilePath = resolveNonManoFilePath(originalManifestPath, nonManoFilePath);
114 final Optional<Path> changedPath = updateNonManoPathInHandler(handler, nonManoType, normalizedFilePath);
115 if (changedPath.isPresent()) {
116 final Map<String, Path> fromAndToPathMap = new HashMap<>();
117 fromAndToPathMap.put(nonManoFilePath, Paths.get(ARTIFACTS_FOLDER).resolve(changedPath.get()));
118 return fromAndToPathMap;
122 .filter(Objects::nonNull)
123 .collect(Collectors.toMap(
124 fromToPathEntry -> fromToPathEntry.keySet().iterator().next(),
125 fromToPathEntry -> fromToPathEntry.values().iterator().next()
127 fromToPathMap.putAll(actualFromToPathMap);
130 return MapUtils.isEmpty(fromToPathMap) ? Optional.empty() : Optional.of(fromToPathMap);
134 * Resolves the non mano file path based on the original manifest path of the onboarded package.
136 * @param originalManifestPath The original path from the onboarded package manifest
137 * @param nonManoFilePath The non mano file path defined in the manifest
138 * @return The resolved and normalized non mano path.
140 private Path resolveNonManoFilePath(final Path originalManifestPath, final String nonManoFilePath) {
141 return originalManifestPath.resolve(Paths.get(nonManoFilePath)).normalize();
145 * Updates the non mano file path in the package file handler based on the non mano type.
147 * @param handler The package file handler
148 * @param nonManoType The Non Mano type of the file to update
149 * @param nonManoOriginalFilePath The Non Mano file original path
150 * @return The new file path if it was updated in the package file handler, otherwise empty.
152 private Optional<Path> updateNonManoPathInHandler(final FileContentHandler handler, final NonManoType nonManoType,
153 final Path nonManoOriginalFilePath) {
154 final Path fixedSourcePath = fixNonManoPath(nonManoOriginalFilePath);
155 if (handler.containsFile(fixedSourcePath.toString())) {
156 final Path newNonManoPath = Paths.get(nonManoType.getType(), nonManoType.getLocation()
157 , fixedSourcePath.getFileName().toString());
158 if (!handler.containsFile(newNonManoPath.toString())) {
159 handler.addFile(newNonManoPath.toString(), handler.remove(fixedSourcePath.toString()));
160 return Optional.of(newNonManoPath);
164 return Optional.empty();
168 * Fix the original non mano file path to the ONAP package file path.
170 * Non mano artifacts that were inside the {@link org.openecomp.sdc.tosca.csar.CSARConstants#ARTIFACTS_FOLDER} path
171 * are not moved when parsed to ONAP package, but the Manifest declaration can still have the {@link
172 * org.openecomp.sdc.tosca.csar.CSARConstants#ARTIFACTS_FOLDER} reference in it. If so, that reference is removed.
174 * @param nonManoOriginalFilePath The original non mano file path
175 * @return The non mano fixed path to ONAP package structure.
177 private Path fixNonManoPath(final Path nonManoOriginalFilePath) {
178 final Path rootArtifactsPath = Paths.get("/", ARTIFACTS_FOLDER);
179 if (nonManoOriginalFilePath.startsWith(rootArtifactsPath)) {
180 return rootArtifactsPath.relativize(nonManoOriginalFilePath);
182 final Path relativeArtifactsPath = Paths.get(ARTIFACTS_FOLDER);
183 if (nonManoOriginalFilePath.startsWith(relativeArtifactsPath)) {
184 return relativeArtifactsPath.relativize(nonManoOriginalFilePath);
187 return nonManoOriginalFilePath;
191 public void updateMainDescriptorPaths(final ToscaServiceModel toscaServiceModel,
192 final Map<String, Path> fromToMovedArtifactMap) {
193 final ServiceTemplate entryDefinition = toscaServiceModel.getServiceTemplates()
194 .get(toscaServiceModel.getEntryDefinitionServiceTemplate());
195 final YamlUtil yamlUtil = new YamlUtil();
196 final String[] entryDefinitionYaml = {yamlUtil.objectToYaml(entryDefinition)};
197 fromToMovedArtifactMap.forEach((fromPath, toPath) -> entryDefinitionYaml[0] = entryDefinitionYaml[0]
198 .replaceAll(fromPath, toPath.toString()));
200 toscaServiceModel.addServiceTemplate(toscaServiceModel.getEntryDefinitionServiceTemplate()
201 , yamlUtil.yamlToObject(entryDefinitionYaml[0], ServiceTemplate.class));
204 private boolean hasMetaMandatoryEntries(final ToscaMetadata toscaMetadata) {
205 final Map<String, String> metaDataEntries = toscaMetadata.getMetaEntries();
206 return metaDataEntries.containsKey(ENTRY_DEFINITIONS.getName()) && metaDataEntries
207 .containsKey(ETSI_ENTRY_MANIFEST.getName())
208 && metaDataEntries.containsKey(ETSI_ENTRY_CHANGE_LOG.getName());
211 private boolean isMetaFilePresent(Map<String, byte[]> handler) {
212 return handler.containsKey(TOSCA_META_PATH_FILE_NAME.getName()) || handler.containsKey(TOSCA_META_ORIG_PATH_FILE_NAME);
215 public ResourceTypeEnum getResourceType(FileContentHandler handler) throws IOException {
216 ToscaMetadata metadata = getMetadata(handler);
217 Manifest manifest = getManifest(handler, metadata.getMetaEntries().get(ETSI_ENTRY_MANIFEST.getName()));
218 return getResourceType(manifest);
221 public ResourceTypeEnum getResourceType(Manifest manifest) {
222 // Valid manifest should contain whether vnf or pnf related metadata data exclusively in SOL004 standard,
223 // validation of manifest done during package upload stage
224 if (manifest != null && !manifest.getMetadata().isEmpty()
225 && MANIFEST_PNF_METADATA.stream().anyMatch(e -> manifest.getMetadata().containsKey(e))) {
226 return ResourceTypeEnum.PNF;
228 // VNF is default resource type
229 return ResourceTypeEnum.VF;
232 public Manifest getManifest(FileContentHandler handler) throws IOException {
233 ToscaMetadata metadata = getMetadata(handler);
234 return getManifest(handler, metadata.getMetaEntries().get(ETSI_ENTRY_MANIFEST.getName()));
237 private Manifest getManifest(FileContentHandler handler, String manifestLocation) throws IOException {
238 try (InputStream manifestInputStream = getManifestInputStream(handler, manifestLocation)) {
239 Manifest onboardingManifest = new SOL004ManifestOnboarding();
240 onboardingManifest.parse(manifestInputStream);
241 return onboardingManifest;
245 public Path getOriginalManifestPath(final FileContentHandler handler) throws IOException {
246 final ToscaMetadata metadata = getOriginalMetadata(handler);
247 final String originalMetadataPath = metadata.getMetaEntries().get(ETSI_ENTRY_MANIFEST.getName());
248 final Path path = Paths.get(originalMetadataPath);
249 return path.getParent() == null ? Paths.get("") : path.getParent();
252 private ToscaMetadata getMetadata(FileContentHandler handler) throws IOException {
253 ToscaMetadata metadata;
254 if (handler.containsFile(TOSCA_META_PATH_FILE_NAME.getName())) {
255 metadata = OnboardingToscaMetadata
256 .parseToscaMetadataFile(handler.getFileContentAsStream(TOSCA_META_PATH_FILE_NAME.getName()));
257 } else if (handler.containsFile(TOSCA_META_ORIG_PATH_FILE_NAME)) {
258 metadata = OnboardingToscaMetadata
259 .parseToscaMetadataFile(handler.getFileContentAsStream(TOSCA_META_ORIG_PATH_FILE_NAME));
261 throw new IOException("TOSCA.meta file not found!");
266 private ToscaMetadata getOriginalMetadata(final FileContentHandler handler) throws IOException {
267 if (handler.containsFile(TOSCA_META_ORIG_PATH_FILE_NAME)) {
268 return OnboardingToscaMetadata
269 .parseToscaMetadataFile(handler.getFileContentAsStream(TOSCA_META_ORIG_PATH_FILE_NAME));
271 throw new IOException(String.format("%s file not found", TOSCA_META_ORIG_PATH_FILE_NAME));
275 private InputStream getManifestInputStream(FileContentHandler handler, String manifestLocation) throws IOException {
277 if (manifestLocation == null || !handler.containsFile(manifestLocation)) {
278 io = handler.getFileContentAsStream(MAIN_SERVICE_TEMPLATE_MF_FILE_NAME);
280 io = handler.getFileContentAsStream(manifestLocation);
284 throw new IOException("Manifest file not found!");