26d45cc7e6ceccbfcb38cf9c2e3a2bb84e3761c3
[vid.git] / vid-app-common / src / main / java / org / openecomp / vid / asdc / rest / RestfulAsdcClient.java
1 /*-\r
2  * ============LICENSE_START=======================================================\r
3  * VID\r
4  * ================================================================================\r
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.\r
6  * ================================================================================\r
7  * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * you may not use this file except in compliance with the License.\r
9  * You may obtain a copy of the License at\r
10  * \r
11  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * \r
13  * Unless required by applicable law or agreed to in writing, software\r
14  * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * See the License for the specific language governing permissions and\r
17  * limitations under the License.\r
18  * ============LICENSE_END=========================================================\r
19  */\r
20 \r
21 package org.openecomp.vid.asdc.rest;\r
22 \r
23 import java.io.IOException;\r
24 import java.io.InputStream;\r
25 import java.net.URI;\r
26 import java.nio.file.Files;\r
27 import java.nio.file.Path;\r
28 import java.nio.file.StandardCopyOption;\r
29 import java.util.Collection;\r
30 import java.util.Collections;\r
31 import java.util.Map;\r
32 import java.util.Map.Entry;\r
33 import java.util.UUID;\r
34 import java.util.logging.Logger;\r
35 import java.util.zip.ZipFile;\r
36 \r
37 import javax.ws.rs.NotFoundException;\r
38 import javax.ws.rs.ProcessingException;\r
39 import javax.ws.rs.WebApplicationException;\r
40 import javax.ws.rs.client.Client;\r
41 import javax.ws.rs.client.ResponseProcessingException;\r
42 import javax.ws.rs.client.WebTarget;\r
43 import javax.ws.rs.core.GenericType;\r
44 import javax.ws.rs.core.MediaType;\r
45 import javax.ws.rs.core.MultivaluedHashMap;\r
46 \r
47 import org.openecomp.vid.asdc.AsdcCatalogException;\r
48 import org.openecomp.vid.asdc.AsdcClient;\r
49 import org.openecomp.vid.asdc.beans.Artifact;\r
50 import org.openecomp.vid.asdc.beans.Resource;\r
51 import org.openecomp.vid.asdc.beans.Service;\r
52 import org.openecomp.vid.asdc.beans.tosca.ToscaCsar;\r
53 import org.openecomp.vid.asdc.beans.tosca.ToscaMeta;\r
54 import org.openecomp.vid.asdc.beans.tosca.ToscaModel;\r
55 import org.openecomp.vid.model.ModelConstants;\r
56 import org.yaml.snakeyaml.Yaml;\r
57 import org.yaml.snakeyaml.error.YAMLException;\r
58 \r
59 import org.openecomp.vid.properties.VidProperties;\r
60 import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;\r
61 \r
62 /**\r
63  * The Class RestfulAsdcClient.\r
64  */\r
65 public class RestfulAsdcClient implements AsdcClient {\r
66 \r
67         /** The Constant LOGGER. */\r
68         private static final Logger LOGGER = Logger.getLogger(RestfulAsdcClient.class.getName());\r
69         \r
70         /** The client. */\r
71         private final Client client;\r
72         \r
73         /** The uri. */\r
74         private final URI uri;\r
75         \r
76         /** The common headers. */\r
77         private final MultivaluedHashMap<String, Object> commonHeaders;\r
78         \r
79         /** The auth. */\r
80         private final String auth;\r
81         \r
82         /**\r
83          * The Class Builder.\r
84          */\r
85         public static class Builder {\r
86         \r
87                 /** The client. */\r
88                 private final Client client;\r
89                 \r
90                 /** The uri. */\r
91                 private final URI uri;\r
92                 \r
93                 /** The auth. */\r
94                 private String auth = null;\r
95                 \r
96                 /**\r
97                  * Instantiates a new builder.\r
98                  *\r
99                  * @param client the client\r
100                  * @param uri the uri\r
101                  */\r
102                 public Builder(Client client, URI uri) {\r
103                         this.client = client;\r
104                         this.client.register(JacksonJsonProvider.class);\r
105                         this.uri = uri;\r
106                 }\r
107                 \r
108                 /**\r
109                  * Auth.\r
110                  *\r
111                  * @param auth the auth\r
112                  * @return the builder\r
113                  */\r
114                 public Builder auth(String auth) {\r
115                         this.auth = auth;\r
116                         return this;\r
117                 }\r
118                 \r
119                 /**\r
120                  * Builds the.\r
121                  *\r
122                  * @return the restful asdc client\r
123                  */\r
124                 public RestfulAsdcClient build() {\r
125                         return new RestfulAsdcClient(this);\r
126                 }\r
127         }\r
128         \r
129         /**\r
130          * Instantiates a new restful asdc client.\r
131          *\r
132          * @param builder the builder\r
133          */\r
134         private RestfulAsdcClient(Builder builder) {\r
135                 client = builder.client;\r
136                 uri = builder.uri;\r
137                 auth = builder.auth;\r
138                 \r
139                 commonHeaders = new MultivaluedHashMap<String, Object> ();\r
140                 commonHeaders.put("X-ECOMP-InstanceID", Collections.singletonList((Object) "VID"));\r
141                 commonHeaders.put("Authorization",  Collections.singletonList((Object) (auth)));\r
142         }\r
143         \r
144         /**\r
145          * Gets the client.\r
146          *\r
147          * @return the client\r
148          */\r
149         private Client getClient() { return client; }\r
150         \r
151         /* (non-Javadoc)\r
152          * @see org.openecomp.vid.asdc.AsdcClient#getResource(java.util.UUID)\r
153          */\r
154         public Resource getResource(UUID uuid) throws AsdcCatalogException {\r
155                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_RESOURCE_API_PATH, ModelConstants.DEFAULT_ASDC_RESOURCE_API_PATH);\r
156                 try {\r
157                         return getClient()\r
158                                         .target(uri)\r
159                                         .path(path + "/" + uuid.toString() + "/metadata")\r
160                                         .request(MediaType.APPLICATION_JSON_TYPE)\r
161                                         .headers(commonHeaders)\r
162                                         .header("Content-Type", MediaType.APPLICATION_JSON)\r
163                                         .get(Resource.class);\r
164                 } catch (ResponseProcessingException e) {\r
165                         //Couldn't convert response to Java type\r
166                         throw new AsdcCatalogException("ASDC response could not be processed", e);\r
167                 } catch (ProcessingException e) {\r
168                         //IO problems during request\r
169                         throw new AsdcCatalogException("Failed to get a response from ASDC service", e);\r
170                 } catch (WebApplicationException e) {\r
171                         //Web service returned data, but the response status wasn't a good one (i.e. non 2xx)\r
172                         throw new AsdcCatalogException(e);\r
173                 }\r
174         }\r
175 \r
176         /* (non-Javadoc)\r
177          * @see org.openecomp.vid.asdc.AsdcClient#getResources()\r
178          */\r
179         public Collection<Resource> getResources() throws AsdcCatalogException {\r
180                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_RESOURCE_API_PATH, ModelConstants.DEFAULT_ASDC_RESOURCE_API_PATH);\r
181                 try {\r
182                         return getClient()\r
183                                         .target(uri)\r
184                                         .path(path)\r
185                                         .request(MediaType.APPLICATION_JSON_TYPE)\r
186                                         .headers(commonHeaders)\r
187                                         .header("Content-Type", MediaType.APPLICATION_JSON)\r
188                                         .get(new GenericType<Collection<Resource>> () {});\r
189                 } catch (ResponseProcessingException e) {\r
190                         //Couldn't convert response to Java type\r
191                         throw new AsdcCatalogException("ASDC response could not be processed", e);\r
192                 } catch (ProcessingException e) {\r
193                         //IO problems during request\r
194                         throw new AsdcCatalogException("Failed to get a response from ASDC service", e);\r
195                 } catch (WebApplicationException e) {\r
196                         //Web service returned data, but the response status wasn't a good one (i.e. non 2xx)\r
197                         throw new AsdcCatalogException(e);\r
198                 }\r
199         }\r
200 \r
201         /* (non-Javadoc)\r
202          * @see org.openecomp.vid.asdc.AsdcClient#getResources(java.util.Map)\r
203          */\r
204         public Collection<Resource> getResources(Map<String, String[]> filter) throws AsdcCatalogException {\r
205                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_RESOURCE_API_PATH, ModelConstants.DEFAULT_ASDC_RESOURCE_API_PATH);\r
206                 WebTarget target = getClient()\r
207                                 .target(uri)\r
208                                 .path(path);\r
209                 \r
210                 for (Entry<String, String[]> filterEntry : filter.entrySet()) {\r
211                         target = target.queryParam(filterEntry.getKey(), (Object []) filterEntry.getValue());\r
212                 }\r
213                 \r
214                 try {\r
215                         return target.request()\r
216                                         .accept(MediaType.APPLICATION_JSON_TYPE)\r
217                                         .headers(commonHeaders)\r
218                                         .header("Content-Type", MediaType.APPLICATION_JSON)\r
219                                         .get(new GenericType<Collection<Resource>> () {});\r
220                 } catch (ResponseProcessingException e) {\r
221                         //Couldn't convert response to Java type\r
222                         throw new AsdcCatalogException("ASDC response could not be processed", e);\r
223                 } catch (ProcessingException e) {\r
224                         //IO problems during request\r
225                         throw new AsdcCatalogException("Failed to get a response from ASDC service", e);\r
226                 } catch (NotFoundException e) {\r
227                         throw e;\r
228                 } catch (WebApplicationException e) {\r
229                         //Web service returned data, but the response status wasn't a good one (i.e. non 2xx)\r
230                         throw new AsdcCatalogException(e);\r
231                 }\r
232         }\r
233 \r
234         /* (non-Javadoc)\r
235          * @see org.openecomp.vid.asdc.AsdcClient#getResourceArtifact(java.util.UUID, java.util.UUID)\r
236          */\r
237         public Artifact getResourceArtifact(UUID resourceUuid, UUID artifactUuid) throws AsdcCatalogException {\r
238                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_RESOURCE_API_PATH, ModelConstants.DEFAULT_ASDC_RESOURCE_API_PATH);\r
239                 try {\r
240                         return getClient()\r
241                                         .target(uri)\r
242                                         .path(path + "/" + resourceUuid + "/artifacts/" + artifactUuid)\r
243                                         .request(MediaType.APPLICATION_JSON_TYPE)\r
244                                         .headers(commonHeaders)\r
245                                         .header("Content-Type", MediaType.APPLICATION_JSON)\r
246                                         .get(Artifact.class);\r
247                 } catch (ResponseProcessingException e) {\r
248                         //Couldn't convert response to Java type\r
249                         throw new AsdcCatalogException("ASDC response could not be processed", e);\r
250                 } catch (ProcessingException e) {\r
251                         //IO problems during request\r
252                         throw new AsdcCatalogException("Failed to get a response from ASDC service", e);\r
253                 } catch (WebApplicationException e) {\r
254                         //Web service returned data, but the response status wasn't a good one (i.e. non 2xx)\r
255                         throw new AsdcCatalogException(e);\r
256                 }\r
257         }\r
258         \r
259         /* (non-Javadoc)\r
260          * @see org.openecomp.vid.asdc.AsdcClient#getService(java.util.UUID)\r
261          */\r
262         public Service getService(UUID uuid) throws AsdcCatalogException {\r
263                 \r
264                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_SVC_API_PATH, ModelConstants.DEFAULT_ASDC_SVC_API_PATH);\r
265                 try {\r
266                         return getClient()\r
267                                         .target(uri)\r
268                                         .path( path + "/" + uuid.toString() + "/metadata")\r
269                                         .request(MediaType.APPLICATION_JSON)\r
270                                         .headers(commonHeaders)\r
271                                         .get(Service.class);\r
272                 } catch (ResponseProcessingException e) {\r
273                         //Couldn't convert response to Java type\r
274                         throw new AsdcCatalogException("ASDC response could not be processed", e);\r
275                 } catch (ProcessingException e) {\r
276                         //IO problems during request\r
277                         throw new AsdcCatalogException("Failed to get a response from ASDC service", e);\r
278                 } catch (WebApplicationException e) {\r
279                         //Web service returned data, but the response status wasn't a good one (i.e. non 2xx)\r
280                         throw new AsdcCatalogException(e);\r
281                 }\r
282         }\r
283 \r
284         /* (non-Javadoc)\r
285          * @see org.openecomp.vid.asdc.AsdcClient#getServices()\r
286          */\r
287         public Collection<Service> getServices() throws AsdcCatalogException {\r
288                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_SVC_API_PATH, ModelConstants.DEFAULT_ASDC_SVC_API_PATH);\r
289                 try {\r
290                         return getClient()\r
291                                         .target(uri)\r
292                                         .path(path)\r
293                                         .request()\r
294                                         .accept(MediaType.APPLICATION_JSON_TYPE)\r
295                                         .headers(commonHeaders)\r
296                                         .header("Content-Type", MediaType.APPLICATION_JSON)\r
297                                         .get(new GenericType<Collection<Service>> () {});\r
298                 } catch (ResponseProcessingException e) {\r
299                         //Couldn't convert response to Java type\r
300                         throw new AsdcCatalogException("ASDC response could not be processed", e);\r
301                 } catch (ProcessingException e) {\r
302                         //IO problems during request\r
303                         throw new AsdcCatalogException("Failed to get a response from ASDC service", e);\r
304                 } catch (WebApplicationException e) {\r
305                         //Web service returned data, but the response status wasn't a good one (i.e. non 2xx)\r
306                         throw new AsdcCatalogException(e);\r
307                 }\r
308         }\r
309 \r
310         /* (non-Javadoc)\r
311          * @see org.openecomp.vid.asdc.AsdcClient#getServices(java.util.Map)\r
312          */\r
313         public Collection<Service> getServices(Map<String, String[]> filter) throws AsdcCatalogException {\r
314                 \r
315                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_SVC_API_PATH, ModelConstants.DEFAULT_ASDC_SVC_API_PATH);\r
316                 WebTarget target = getClient()\r
317                                 .target(uri)\r
318                                 .path(path);\r
319                 \r
320                         \r
321                 for (Entry<String, String[]> filterEntry : filter.entrySet()) {\r
322                         target = target.queryParam(filterEntry.getKey(), (Object []) filterEntry.getValue());\r
323                 }\r
324                 \r
325                 try {\r
326                         return target.request()\r
327                                         .accept(MediaType.APPLICATION_JSON_TYPE)\r
328                                         .headers(commonHeaders)\r
329                                         .header("Content-Type", MediaType.APPLICATION_JSON)\r
330                                         .get(new GenericType<Collection<Service>> () {});\r
331                 } catch (ResponseProcessingException e) {\r
332                         //Couldn't convert response to Java type\r
333                         throw new AsdcCatalogException("ASDC response could not be processed", e);\r
334                 } catch (ProcessingException e) {\r
335                         //IO problems during request\r
336                         throw new AsdcCatalogException("Failed to get a response from ASDC service", e);\r
337                 } catch (NotFoundException e) {\r
338                         throw e;\r
339                 } catch (WebApplicationException e) {\r
340                         //Web service returned data, but the response status wasn't a good one (i.e. non 2xx)\r
341                         throw new AsdcCatalogException(e);\r
342                 }\r
343         }\r
344         \r
345         /* (non-Javadoc)\r
346          * @see org.openecomp.vid.asdc.AsdcClient#getServiceArtifact(java.util.UUID, java.util.UUID)\r
347          */\r
348         public Artifact getServiceArtifact(UUID serviceUuid, UUID artifactUuid) throws AsdcCatalogException {\r
349                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_SVC_API_PATH, ModelConstants.DEFAULT_ASDC_SVC_API_PATH);\r
350                 try {\r
351                         return getClient()\r
352                                         .target(uri)\r
353                                         .path(path + "/" + serviceUuid + "/artifacts/" + artifactUuid)\r
354                                         .request(MediaType.APPLICATION_JSON_TYPE)\r
355                                         .headers(commonHeaders)\r
356                                         .header("Content-Type", MediaType.APPLICATION_JSON)\r
357                                         .get(Artifact.class);\r
358                 } catch (ResponseProcessingException e) {\r
359                         //Couldn't convert response to Java type\r
360                         throw new AsdcCatalogException("ASDC response could not be processed", e);\r
361                 } catch (ProcessingException e) {\r
362                         //IO problems during request\r
363                         throw new AsdcCatalogException("Failed to get a response from ASDC service", e);\r
364                 } catch (WebApplicationException e) {\r
365                         //Web service returned data, but the response status wasn't a good one (i.e. non 2xx)\r
366                         throw new AsdcCatalogException(e);\r
367                 }\r
368         }\r
369 \r
370         /* (non-Javadoc)\r
371          * @see org.openecomp.vid.asdc.AsdcClient#getResourceToscaModel(java.util.UUID)\r
372          */\r
373         public ToscaCsar getResourceToscaModel(UUID resourceUuid) throws AsdcCatalogException {\r
374                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_RESOURCE_API_PATH, ModelConstants.DEFAULT_ASDC_RESOURCE_API_PATH);\r
375                 try (final InputStream csarInputStream = (InputStream) getClient()\r
376                                 .target(uri)\r
377                                 .path(path + "/" + resourceUuid + "/toscaModel")\r
378                                 .request(MediaType.APPLICATION_OCTET_STREAM_TYPE)\r
379                                 .headers(commonHeaders)\r
380                                 .header("Content-Type", MediaType.APPLICATION_OCTET_STREAM)\r
381                                 .get(InputStream.class)) {\r
382 \r
383                         return getToscaModel(csarInputStream);\r
384                 } catch (IOException e) {\r
385                         throw new AsdcCatalogException("Failed to retrieve resource TOSCA model from ASDC", e);\r
386                 }\r
387         }\r
388 \r
389         /* (non-Javadoc)\r
390          * @see org.openecomp.vid.asdc.AsdcClient#getServiceToscaModel(java.util.UUID)\r
391          */\r
392         public ToscaCsar getServiceToscaModel(UUID serviceUuid) throws AsdcCatalogException {\r
393                 String path = VidProperties.getPropertyWithDefault(ModelConstants.ASDC_SVC_API_PATH, ModelConstants.DEFAULT_ASDC_SVC_API_PATH);\r
394                 try {\r
395                         final InputStream csarInputStream = (InputStream) getClient()\r
396                                         .target(uri)\r
397                                         .path(path + "/" + serviceUuid + "/toscaModel")\r
398                                         .request(MediaType.APPLICATION_OCTET_STREAM_TYPE)\r
399                                         .headers(commonHeaders)\r
400                                         .header("Content-Type", MediaType.APPLICATION_OCTET_STREAM)\r
401                                         .get(InputStream.class);\r
402                                         \r
403                         return getToscaModel(csarInputStream);\r
404                 } catch (ResponseProcessingException e) {\r
405                         //Couldn't convert response to Java type\r
406                         throw new AsdcCatalogException("ASDC response could not be processed", e);\r
407                 } catch (ProcessingException e) {\r
408                         //IO problems during request\r
409                         throw new AsdcCatalogException("Failed to get a response from ASDC service", e);\r
410                 } catch (WebApplicationException e) {\r
411                         //Web service returned data, but the response status wasn't a good one (i.e. non 2xx)\r
412                         throw new AsdcCatalogException(e);\r
413                 }\r
414         }\r
415         \r
416         /**\r
417          * Gets the tosca model.\r
418          *\r
419          * @param csarInputStream the csar input stream\r
420          * @return the tosca model\r
421          * @throws AsdcCatalogException the asdc catalog exception\r
422          */\r
423         private ToscaCsar getToscaModel(InputStream csarInputStream) throws AsdcCatalogException {\r
424                 final Path csarFile;\r
425                 \r
426                 try {\r
427                         csarFile = Files.createTempFile("csar", ".zip");\r
428                         Files.copy(csarInputStream, csarFile, StandardCopyOption.REPLACE_EXISTING);\r
429                 } catch (IOException e) {\r
430                         throw new AsdcCatalogException("Caught IOException while creating CSAR", e);\r
431                 }\r
432                 \r
433                 try (final ZipFile csar = new ZipFile(csarFile.toFile())) {\r
434                         \r
435                         final InputStream toscaMetaStream = csar.getInputStream(csar.getEntry("TOSCA-Metadata/TOSCA.meta"));\r
436                         final ToscaMeta toscaMeta = new ToscaMeta.Builder(toscaMetaStream).build();\r
437                         final String entryDefinitions = toscaMeta.get("Entry-Definitions");\r
438                         final InputStream toscaParentEntryYamlStream = csar.getInputStream(csar.getEntry(entryDefinitions));\r
439                         \r
440                         try {\r
441                                 final Yaml yaml = new Yaml();\r
442                                 final ToscaModel parentModel = yaml.loadAs(toscaParentEntryYamlStream, ToscaModel.class);\r
443         \r
444                                 final ToscaCsar.Builder csarBuilder = new ToscaCsar.Builder(parentModel);\r
445                                 \r
446                                 for (Map<String, Map<String, String>> imports : parentModel.getImports()) {\r
447                                         for (Entry<String, Map<String, String>> entry : imports.entrySet()) {\r
448                                                 final InputStream toscaChildEntryYamlStream = csar.getInputStream(csar.getEntry("Definitions/" + entry.getValue().get("file")));\r
449                                                 final ToscaModel childModel = yaml.loadAs(toscaChildEntryYamlStream, ToscaModel.class);\r
450                                                 csarBuilder.addVnf(childModel);\r
451                                         }\r
452                                 }\r
453                                 \r
454                                 return csarBuilder.build();\r
455                         } catch (YAMLException e) {\r
456                                 throw new AsdcCatalogException("Caught exception while processing TOSCA YAML", e);\r
457                         }\r
458                 } catch (IOException e) {\r
459                         throw new AsdcCatalogException("Caught IOException while processing CSAR", e);\r
460                 }\r
461         }\r
462 }\r