0ade7bf1e9cce149605d746ed49b46cf88300f8f
[so/adapters/so-cnf-adapter.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2023 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  *
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.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc;
21
22 import static com.google.common.base.Splitter.on;
23 import static com.google.common.collect.Iterables.filter;
24 import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.APPLICATION_NAME_PARAM_NAME;
25 import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.APPLICATION_VERSION_PARAM_NAME;
26 import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.DEPLOYMENT_ITEMS_PARAM_NAME;
27 import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.DESCRIPTOR_ID_PARAM_NAME;
28 import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.DESCRIPTOR_INVARIANT_ID_PARAM_NAME;
29 import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.PROVIDER_PARAM_NAME;
30 import java.io.ByteArrayInputStream;
31 import java.io.ByteArrayOutputStream;
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.NoSuchElementException;
42 import java.util.Set;
43 import java.util.zip.ZipEntry;
44 import java.util.zip.ZipInputStream;
45
46 import com.google.gson.JsonArray;
47 import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.FileNotFoundInCsarException;
48 import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.PropertyNotFoundException;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51 import org.springframework.stereotype.Service;
52 import org.yaml.snakeyaml.Yaml;
53 import com.google.common.io.ByteStreams;
54 import com.google.gson.Gson;
55 import com.google.gson.JsonElement;
56 import com.google.gson.JsonObject;
57
58 /**
59  *
60  * @author Waqas Ikram (waqas.ikram@est.tech)
61  *
62  */
63 @Service
64 public class SdcCsarPackageParser {
65     private static final String TOCSA_METADATA_FILE_PATH = "TOSCA-Metadata/TOSCA.meta";
66     private static final String ENTRY_DEFINITIONS_ENTRY = "Entry-Definitions";
67
68     private static final Logger logger = LoggerFactory.getLogger(SdcCsarPackageParser.class);
69
70     public Map<String, Object> getAsdProperties(final byte[] onapPackage) {
71
72         try (final ByteArrayInputStream stream = new ByteArrayInputStream(onapPackage);
73                 final ZipInputStream zipInputStream = new ZipInputStream(stream);) {
74             final String asdLocation = getAsdLocation(zipInputStream);
75             final String onapAsdContent = getFileInZip(zipInputStream, asdLocation).toString();
76             logger.debug("ASD CONTENTS: {}", onapAsdContent);
77             final JsonObject root = new Gson().toJsonTree(new Yaml().load(onapAsdContent)).getAsJsonObject();
78
79             final JsonObject topologyTemplates = child(root, "topology_template");
80             final JsonObject nodeTemplates = child(topologyTemplates, "node_templates");
81             for (final JsonObject child : children(nodeTemplates)) {
82                 final String type = childElement(child, "type").getAsString();
83                 if ("tosca.nodes.asd".equals(type)) {
84                     final JsonObject properties = child(child, "properties");
85                     logger.debug("properties: {}", properties.toString());
86                     final Map<String, Object> propertiesValues = new HashMap<>();
87                     propertiesValues.put(DESCRIPTOR_ID_PARAM_NAME,
88                             getStringValue(properties, DESCRIPTOR_ID_PARAM_NAME));
89                     propertiesValues.put(DESCRIPTOR_INVARIANT_ID_PARAM_NAME,
90                             getStringValue(properties, DESCRIPTOR_INVARIANT_ID_PARAM_NAME));
91                     propertiesValues.put(PROVIDER_PARAM_NAME, getStringValue(properties, PROVIDER_PARAM_NAME));
92                     propertiesValues.put(APPLICATION_NAME_PARAM_NAME,
93                             getStringValue(properties, APPLICATION_NAME_PARAM_NAME));
94                     propertiesValues.put(APPLICATION_VERSION_PARAM_NAME,
95                             getStringValue(properties, APPLICATION_VERSION_PARAM_NAME));
96                     propertiesValues.put(DEPLOYMENT_ITEMS_PARAM_NAME, getDeploymentItems(child));
97
98                     return propertiesValues;
99
100                 }
101             }
102
103
104         } catch (final Exception exception) {
105             throw new IllegalArgumentException("Unable to parser CSAR package", exception);
106         }
107         return Collections.emptyMap();
108     }
109
110     private String getStringValue(final JsonObject properties, final String key) {
111         final JsonElement element = properties.get(key);
112         if (element != null && element.isJsonPrimitive()) {
113             return element.getAsString();
114         }
115         logger.warn("'{}' value is not Primitive or null val:{}", key, element != null ? element.toString() : null);
116         return null;
117     }
118
119     private List<DeploymentItem> getDeploymentItems(final JsonObject child) {
120         final List<DeploymentItem> items = new ArrayList<>();
121
122         final JsonObject artifacts = child(child, "artifacts");
123         artifacts.keySet().forEach(key -> {
124             final JsonObject element = artifacts.getAsJsonObject(key);
125             final JsonObject artifactsProperties = child(element, "properties");
126             final List<String> lcp = getLifecycleParameters(artifactsProperties);
127             items.add(new DeploymentItem().name(key).itemId(getStringValue(artifactsProperties, "itemId"))
128                     .file(getStringValue(element, "file"))
129                     .deploymentOrder(getStringValue(artifactsProperties, "deployment_order")).lifecycleParameters(lcp));
130         });
131         return items;
132     }
133
134     private List<String> getLifecycleParameters(final JsonObject artifactsProperties) {
135         final JsonArray lcParameters = childElement(artifactsProperties, "lifecycle_parameters").getAsJsonArray();
136         final List<String> lifecycleParameters = new ArrayList<>();
137         if(lcParameters != null) {
138             final Iterator<JsonElement> it = lcParameters.iterator();
139             while(it.hasNext()){
140                 lifecycleParameters.add(it.next().getAsString());
141             }
142         }
143         return lifecycleParameters;
144     }
145
146     private String getAsdLocation(final ZipInputStream zipInputStream) throws IOException {
147
148         try (final ByteArrayOutputStream fileContent = getFileInZip(zipInputStream, TOCSA_METADATA_FILE_PATH);) {
149             final String toscaMetadata = new String(fileContent.toByteArray());
150             if (!toscaMetadata.isEmpty()) {
151                 final String entry =
152                         filter(on("\n").split(toscaMetadata), line -> line.contains(ENTRY_DEFINITIONS_ENTRY)).iterator()
153                                 .next();
154                 return entry.replace(ENTRY_DEFINITIONS_ENTRY + ":", "").trim();
155             }
156             final String message = "Unable to find valid Tosca Path";
157             logger.error(message);
158             throw new FileNotFoundInCsarException(message);
159         }
160     }
161
162     public ByteArrayOutputStream getFileInZip(final ZipInputStream zipInputStream, final String path)
163             throws IOException {
164         ZipEntry zipEntry;
165         final Set<String> items = new HashSet<>();
166         while ((zipEntry = zipInputStream.getNextEntry()) != null) {
167             items.add(zipEntry.getName());
168             if (zipEntry.getName().matches(path)) {
169                 final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
170                 ByteStreams.copy(zipInputStream, byteArrayOutputStream);
171                 return byteArrayOutputStream;
172             }
173         }
174         logger.error("Unable to find the {} in archive found: {}", path, items);
175         throw new NoSuchElementException("Unable to find the " + path + " in archive found: " + items);
176     }
177
178     private JsonObject child(final JsonObject parent, final String name) {
179         return childElement(parent, name).getAsJsonObject();
180     }
181
182     private JsonElement childElement(final JsonObject parent, final String name) {
183         final JsonElement child = parent.get(name);
184         if (child == null) {
185             final String message = "Missing child " + name;
186             logger.error(message);
187             throw new PropertyNotFoundException(message);
188         }
189         return child;
190     }
191
192     private Collection<JsonObject> children(final JsonObject parent) {
193         final ArrayList<JsonObject> childElements = new ArrayList<>();
194         parent.keySet().stream().forEach(childKey -> {
195             if (parent.get(childKey).isJsonObject()) {
196                 childElements.add(parent.get(childKey).getAsJsonObject());
197             }
198         });
199         return childElements;
200     }
201 }