Fix checkstyle violations in sdc/jtosca
[sdc/sdc-tosca.git] / src / main / java / org / onap / sdc / toscaparser / api / prereq / CSAR.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. 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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.sdc.toscaparser.api.prereq;
22
23 import org.onap.sdc.toscaparser.api.ImportsLoader;
24 import org.onap.sdc.toscaparser.api.common.JToscaValidationIssue;
25 import org.onap.sdc.toscaparser.api.utils.ThreadLocalsHolder;
26 import org.onap.sdc.toscaparser.api.utils.UrlUtils;
27
28 import java.io.BufferedOutputStream;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.FileOutputStream;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.io.RandomAccessFile;
35 import java.net.URL;
36 import java.nio.file.Files;
37 import java.nio.file.Path;
38 import java.nio.file.Paths;
39 import java.nio.file.StandardCopyOption;
40 import java.util.*;
41 import java.util.zip.ZipEntry;
42 import java.util.zip.ZipFile;
43 import java.util.zip.ZipInputStream;
44
45 import org.onap.sdc.toscaparser.api.common.JToscaException;
46 import org.onap.sdc.toscaparser.api.utils.JToscaErrorCodes;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.yaml.snakeyaml.Yaml;
50
51 public class CSAR {
52
53     private static Logger log = LoggerFactory.getLogger(CSAR.class.getName());
54     private static final ArrayList<String> META_PROPERTIES_FILES = new ArrayList<>(Arrays.asList("TOSCA-Metadata/TOSCA.meta", "csar.meta"));
55
56     private String path;
57     private boolean isFile;
58     private boolean isValidated;
59     private boolean errorCaught;
60     private String csar;
61     private String tempDir;
62     //    private Metadata metaData;
63     private File tempFile;
64     private LinkedHashMap<String, LinkedHashMap<String, Object>> metaProperties;
65
66     public CSAR(String csarPath, boolean aFile) {
67         path = csarPath;
68         isFile = aFile;
69         isValidated = false;
70         errorCaught = false;
71         csar = null;
72         tempDir = null;
73         tempFile = null;
74         metaProperties = new LinkedHashMap<>();
75     }
76
77     public boolean validate() throws JToscaException {
78         isValidated = true;
79
80         //validate that the file or URL exists
81
82         if (isFile) {
83             File f = new File(path);
84             if (!f.isFile()) {
85                 ThreadLocalsHolder.getCollector().appendValidationIssue(new JToscaValidationIssue("JE220", String.format("\"%s\" is not a file", path)));
86                 return false;
87             } else {
88                 this.csar = path;
89             }
90         } else {
91             if (!UrlUtils.validateUrl(path)) {
92                 ThreadLocalsHolder.getCollector().appendValidationIssue(new JToscaValidationIssue("JE221", String.format("ImportError: \"%s\" does not exist", path)));
93                 return false;
94             }
95             // get it to a local file
96             try {
97                 File tempFile = File.createTempFile("csartmp", ".csar");
98                 Path ptf = Paths.get(tempFile.getPath());
99                 URL webfile = new URL(path);
100                 InputStream in = webfile.openStream();
101                 Files.copy(in, ptf, StandardCopyOption.REPLACE_EXISTING);
102             } catch (Exception e) {
103                 ThreadLocalsHolder.getCollector().appendValidationIssue(new JToscaValidationIssue("JE222", "ImportError: failed to load CSAR from " + path));
104                 return false;
105             }
106
107             log.debug("CSAR - validate - currently only files are supported");
108             return false;
109         }
110
111         _parseAndValidateMetaProperties();
112
113         if (errorCaught) {
114             return false;
115         }
116
117         // validate that external references in the main template actually exist and are accessible
118         _validateExternalReferences();
119
120         return !errorCaught;
121
122     }
123
124     private void _parseAndValidateMetaProperties() throws JToscaException {
125
126         ZipFile zf = null;
127
128         try {
129
130             // validate that it is a valid zip file
131             RandomAccessFile raf = new RandomAccessFile(csar, "r");
132             long n = raf.readInt();
133             raf.close();
134             // check if Zip's magic number
135             if (n != 0x504B0304) {
136                 String errorString = String.format("\"%s\" is not a valid zip file", csar);
137                 log.error(errorString);
138                 throw new JToscaException(errorString, JToscaErrorCodes.INVALID_CSAR_FORMAT.getValue());
139             }
140
141             // validate that it contains the metadata file in the correct location
142             zf = new ZipFile(csar);
143             ZipEntry ze = zf.getEntry("TOSCA-Metadata/TOSCA.meta");
144             if (ze == null) {
145
146                 String errorString = String.format(
147                         "\"%s\" is not a valid CSAR as it does not contain the " +
148                                 "required file \"TOSCA.meta\" in the folder \"TOSCA-Metadata\"", csar);
149                 log.error(errorString);
150                 throw new JToscaException(errorString, JToscaErrorCodes.MISSING_META_FILE.getValue());
151             }
152
153             //Going over expected metadata files and parsing them
154             for (String metaFile : META_PROPERTIES_FILES) {
155
156                 byte ba[] = new byte[4096];
157                 ze = zf.getEntry(metaFile);
158                 if (ze != null) {
159                     InputStream inputStream = zf.getInputStream(ze);
160                     n = inputStream.read(ba, 0, 4096);
161                     String md = new String(ba);
162                     md = md.substring(0, (int) n);
163
164                     String errorString = String.format(
165                             "The file \"%s\" in the" +
166                                     " CSAR \"%s\" does not contain valid YAML content", ze.getName(), csar);
167
168                     try {
169                         Yaml yaml = new Yaml();
170                         Object mdo = yaml.load(md);
171                         if (!(mdo instanceof LinkedHashMap)) {
172                             log.error(errorString);
173                             throw new JToscaException(errorString, JToscaErrorCodes.INVALID_META_YAML_CONTENT.getValue());
174                         }
175
176                         String[] split = ze.getName().split("/");
177                         String fileName = split[split.length - 1];
178
179                         if (!metaProperties.containsKey(fileName)) {
180                             metaProperties.put(fileName, (LinkedHashMap<String, Object>) mdo);
181                         }
182                     } catch (Exception e) {
183                         log.error(errorString);
184                         throw new JToscaException(errorString, JToscaErrorCodes.INVALID_META_YAML_CONTENT.getValue());
185                     }
186                 }
187             }
188
189             // verify it has "Entry-Definition"
190             String edf = _getMetadata("Entry-Definitions");
191             if (edf == null) {
192                 String errorString = String.format(
193                         "The CSAR \"%s\" is missing the required metadata " +
194                                 "\"Entry-Definitions\" in \"TOSCA-Metadata/TOSCA.meta\"", csar);
195                 log.error(errorString);
196                 throw new JToscaException(errorString, JToscaErrorCodes.ENTRY_DEFINITION_NOT_DEFINED.getValue());
197             }
198
199             //validate that "Entry-Definitions' metadata value points to an existing file in the CSAR
200             boolean foundEDF = false;
201             Enumeration<? extends ZipEntry> entries = zf.entries();
202             while (entries.hasMoreElements()) {
203                 ze = entries.nextElement();
204                 if (ze.getName().equals(edf)) {
205                     foundEDF = true;
206                     break;
207                 }
208             }
209             if (!foundEDF) {
210                 String errorString = String.format(
211                         "The \"Entry-Definitions\" file defined in the CSAR \"%s\" does not exist", csar);
212                 log.error(errorString);
213                 throw new JToscaException(errorString, JToscaErrorCodes.MISSING_ENTRY_DEFINITION_FILE.getValue());
214             }
215         } catch (JToscaException e) {
216             //ThreadLocalsHolder.getCollector().appendCriticalException(e.getMessage());
217             throw e;
218         } catch (Exception e) {
219             ThreadLocalsHolder.getCollector().appendValidationIssue(new JToscaValidationIssue("JE223", "ValidationError: " + e.getMessage()));
220             errorCaught = true;
221         }
222
223         try {
224             if (zf != null) {
225                 zf.close();
226             }
227         } catch (IOException e) {
228         }
229     }
230
231     public void cleanup() {
232         try {
233             if (tempFile != null) {
234                 tempFile.delete();
235             }
236         } catch (Exception e) {
237         }
238     }
239
240     private String _getMetadata(String key) throws JToscaException {
241         if (!isValidated) {
242             validate();
243         }
244         Object value = _getMetaProperty("TOSCA.meta").get(key);
245         return value != null ? value.toString() : null;
246     }
247
248     public String getAuthor() throws JToscaException {
249         return _getMetadata("Created-By");
250     }
251
252     public String getVersion() throws JToscaException {
253         return _getMetadata("CSAR-Version");
254     }
255
256     public LinkedHashMap<String, LinkedHashMap<String, Object>> getMetaProperties() {
257         return metaProperties;
258     }
259
260     private LinkedHashMap<String, Object> _getMetaProperty(String propertiesFile) {
261         return metaProperties.get(propertiesFile);
262     }
263
264     public String getMainTemplate() throws JToscaException {
265         String entryDef = _getMetadata("Entry-Definitions");
266         ZipFile zf;
267         boolean ok = false;
268         try {
269             zf = new ZipFile(path);
270             ok = (zf.getEntry(entryDef) != null);
271             zf.close();
272         } catch (IOException e) {
273             if (!ok) {
274                 log.error("CSAR - getMainTemplate - failed to open {}", path);
275             }
276         }
277         if (ok) {
278             return entryDef;
279         } else {
280             return null;
281         }
282     }
283
284     @SuppressWarnings("unchecked")
285     public LinkedHashMap<String, Object> getMainTemplateYaml() throws JToscaException {
286         String mainTemplate = tempDir + File.separator + getMainTemplate();
287         if (mainTemplate != null) {
288             try (InputStream input = new FileInputStream(new File(mainTemplate));) {
289                 Yaml yaml = new Yaml();
290                 Object data = yaml.load(input);
291                 if (!(data instanceof LinkedHashMap)) {
292                     throw new IOException();
293                 }
294                 return (LinkedHashMap<String, Object>) data;
295             } catch (Exception e) {
296                 ThreadLocalsHolder.getCollector().appendValidationIssue(new JToscaValidationIssue("JE224", String.format(
297                         "The file \"%s\" in the CSAR \"%s\" does not " +
298                                 "contain valid TOSCA YAML content",
299                         mainTemplate, csar)));
300             }
301         }
302         return null;
303     }
304
305     public String getDescription() throws JToscaException {
306         String desc = _getMetadata("Description");
307         if (desc != null) {
308             return desc;
309         }
310
311         Map<String, Object> metaData = metaProperties.get("TOSCA.meta");
312         metaData.put("Description", getMainTemplateYaml().get("description"));
313         return _getMetadata("Description");
314     }
315
316     public String getTempDir() {
317         return tempDir;
318     }
319
320     public void decompress() throws IOException, JToscaException {
321         if (!isValidated) {
322             validate();
323         }
324
325         if (tempDir == null || tempDir.isEmpty()) {
326             tempDir = Files.createTempDirectory("JTP").toString();
327             unzip(path, tempDir);
328         }
329     }
330
331     private void _validateExternalReferences() throws JToscaException {
332         // Extracts files referenced in the main template
333         // These references are currently supported:
334         // * imports
335         // * interface implementations
336         // * artifacts
337         try {
338             decompress();
339             String mainTplFile = getMainTemplate();
340             if (mainTplFile == null) {
341                 return;
342             }
343
344             LinkedHashMap<String, Object> mainTpl = getMainTemplateYaml();
345             if (mainTpl.get("imports") != null) {
346                 // this loads the imports
347                 ImportsLoader il = new ImportsLoader((ArrayList<Object>) mainTpl.get("imports"),
348                         tempDir + File.separator + mainTplFile,
349                         (Object) null,
350                         (LinkedHashMap<String, Object>) null);
351             }
352
353             if (mainTpl.get("topology_template") != null) {
354                 LinkedHashMap<String, Object> topologyTemplate =
355                         (LinkedHashMap<String, Object>) mainTpl.get("topology_template");
356
357                 if (topologyTemplate.get("node_templates") != null) {
358                     LinkedHashMap<String, Object> nodeTemplates =
359                             (LinkedHashMap<String, Object>) topologyTemplate.get("node_templates");
360                     for (String nodeTemplateKey : nodeTemplates.keySet()) {
361                         LinkedHashMap<String, Object> nodeTemplate =
362                                 (LinkedHashMap<String, Object>) nodeTemplates.get(nodeTemplateKey);
363                         if (nodeTemplate.get("artifacts") != null) {
364                             LinkedHashMap<String, Object> artifacts =
365                                     (LinkedHashMap<String, Object>) nodeTemplate.get("artifacts");
366                             for (String artifactKey : artifacts.keySet()) {
367                                 Object artifact = artifacts.get(artifactKey);
368                                 if (artifact instanceof String) {
369                                     _validateExternalReference(mainTplFile, (String) artifact, true);
370                                 } else if (artifact instanceof LinkedHashMap) {
371                                     String file = (String) ((LinkedHashMap<String, Object>) artifact).get("file");
372                                     if (file != null) {
373                                         _validateExternalReference(mainTplFile, file, true);
374                                     }
375                                 } else {
376                                     ThreadLocalsHolder.getCollector().appendValidationIssue(new JToscaValidationIssue("JE225", String.format(
377                                             "ValueError: Unexpected artifact definition for \"%s\"",
378                                             artifactKey)));
379                                     errorCaught = true;
380                                 }
381                             }
382                         }
383                         if (nodeTemplate.get("interfaces") != null) {
384                             LinkedHashMap<String, Object> interfaces =
385                                     (LinkedHashMap<String, Object>) nodeTemplate.get("interfaces");
386                             for (String interfaceKey : interfaces.keySet()) {
387                                 LinkedHashMap<String, Object> _interface =
388                                         (LinkedHashMap<String, Object>) interfaces.get(interfaceKey);
389                                 for (String operationKey : _interface.keySet()) {
390                                     Object operation = _interface.get(operationKey);
391                                     if (operation instanceof String) {
392                                         _validateExternalReference(mainTplFile, (String) operation, false);
393                                     } else if (operation instanceof LinkedHashMap) {
394                                         String imp = (String) ((LinkedHashMap<String, Object>) operation).get("implementation");
395                                         if (imp != null) {
396                                             _validateExternalReference(mainTplFile, imp, true);
397                                         }
398                                     }
399                                 }
400                             }
401                         }
402                     }
403                 }
404             }
405         } catch (IOException e) {
406             errorCaught = true;
407         } finally {
408             // delete tempDir (only here?!?)
409             File fdir = new File(tempDir);
410             deleteDir(fdir);
411             tempDir = null;
412         }
413     }
414
415     public static void deleteDir(File fdir) {
416         try {
417             if (fdir.isDirectory()) {
418                 for (File c : fdir.listFiles())
419                     deleteDir(c);
420             }
421             fdir.delete();
422         } catch (Exception e) {
423         }
424     }
425
426     private void _validateExternalReference(String tplFile, String resourceFile, boolean raiseExc) {
427         // Verify that the external resource exists
428
429         // If resource_file is a URL verify that the URL is valid.
430         // If resource_file is a relative path verify that the path is valid
431         // considering base folder (self.temp_dir) and tpl_file.
432         // Note that in a CSAR resource_file cannot be an absolute path.
433         if (UrlUtils.validateUrl(resourceFile)) {
434             String msg = String.format("URLException: The resource at \"%s\" cannot be accessed", resourceFile);
435             try {
436                 if (UrlUtils.isUrlAccessible(resourceFile)) {
437                     return;
438                 } else {
439                     ThreadLocalsHolder.getCollector().appendValidationIssue(new JToscaValidationIssue("JE226", msg));
440                     errorCaught = true;
441                 }
442             } catch (Exception e) {
443                 ThreadLocalsHolder.getCollector().appendValidationIssue(new JToscaValidationIssue("JE227", msg));
444             }
445         }
446
447         String dirPath = Paths.get(tplFile).getParent().toString();
448         String filePath = tempDir + File.separator + dirPath + File.separator + resourceFile;
449         File f = new File(filePath);
450         if (f.isFile()) {
451             return;
452         }
453
454         if (raiseExc) {
455             ThreadLocalsHolder.getCollector().appendValidationIssue(new JToscaValidationIssue("JE228", String.format(
456                     "ValueError: The resource \"%s\" does not exist", resourceFile)));
457         }
458         errorCaught = true;
459     }
460
461     private void unzip(String zipFilePath, String destDirectory) throws IOException {
462         File destDir = new File(destDirectory);
463         if (!destDir.exists()) {
464             destDir.mkdir();
465         }
466
467         try (ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));) {
468             ZipEntry entry = zipIn.getNextEntry();
469             // iterates over entries in the zip file
470             while (entry != null) {
471                 // create all directories needed for nested items
472                 String[] parts = entry.getName().split("/");
473                 String s = destDirectory + File.separator;
474                 for (int i = 0; i < parts.length - 1; i++) {
475                     s += parts[i];
476                     File idir = new File(s);
477                     if (!idir.exists()) {
478                         idir.mkdir();
479                     }
480                     s += File.separator;
481                 }
482                 String filePath = destDirectory + File.separator + entry.getName();
483                 if (!entry.isDirectory()) {
484                     // if the entry is a file, extracts it
485                     extractFile(zipIn, filePath);
486                 } else {
487                     // if the entry is a directory, make the directory
488                     File dir = new File(filePath);
489                     dir.mkdir();
490                 }
491                 zipIn.closeEntry();
492                 entry = zipIn.getNextEntry();
493             }
494         }
495     }
496
497     /**
498      * Extracts a zip entry (file entry)
499      *
500      * @param zipIn
501      * @param filePath
502      * @throws IOException
503      */
504     private static final int BUFFER_SIZE = 4096;
505
506     private void extractFile(ZipInputStream zipIn, String filePath) throws IOException {
507         //BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
508         try (FileOutputStream fos = new FileOutputStream(filePath);
509              BufferedOutputStream bos = new BufferedOutputStream(fos);) {
510             byte[] bytesIn = new byte[BUFFER_SIZE];
511             int read = 0;
512             while ((read = zipIn.read(bytesIn)) != -1) {
513                 bos.write(bytesIn, 0, read);
514             }
515         }
516     }
517
518 }       
519
520 /*python
521
522 from toscaparser.common.exception import ValidationIssueCollector
523 from toscaparser.common.exception import URLException
524 from toscaparser.common.exception import ValidationError
525 from toscaparser.imports import ImportsLoader
526 from toscaparser.utils.gettextutils import _
527 from toscaparser.utils.urlutils import UrlUtils
528
529 try:  # Python 2.x
530     from BytesIO import BytesIO
531 except ImportError:  # Python 3.x
532     from io import BytesIO
533
534
535 class CSAR(object):
536
537     def __init__(self, csar_file, a_file=True):
538         self.path = csar_file
539         self.a_file = a_file
540         self.is_validated = False
541         self.error_caught = False
542         self.csar = None
543         self.temp_dir = None
544
545     def validate(self):
546         """Validate the provided CSAR file."""
547
548         self.is_validated = True
549
550         # validate that the file or URL exists
551         missing_err_msg = (_('"%s" does not exist.') % self.path)
552         if self.a_file:
553             if not os.path.isfile(self.path):
554                 ValidationIssueCollector.appendException(
555                     ValidationError(message=missing_err_msg))
556                 return False
557             else:
558                 self.csar = self.path
559         else:  # a URL
560             if not UrlUtils.validate_url(self.path):
561                 ValidationIssueCollector.appendException(
562                     ValidationError(message=missing_err_msg))
563                 return False
564             else:
565                 response = requests.get(self.path)
566                 self.csar = BytesIO(response.content)
567
568         # validate that it is a valid zip file
569         if not zipfile.is_zipfile(self.csar):
570             err_msg = (_('"%s" is not a valid zip file.') % self.path)
571             ValidationIssueCollector.appendException(
572                 ValidationError(message=err_msg))
573             return False
574
575         # validate that it contains the metadata file in the correct location
576         self.zfile = zipfile.ZipFile(self.csar, 'r')
577         filelist = self.zfile.namelist()
578         if 'TOSCA-Metadata/TOSCA.meta' not in filelist:
579             err_msg = (_('"%s" is not a valid CSAR as it does not contain the '
580                          'required file "TOSCA.meta" in the folder '
581                          '"TOSCA-Metadata".') % self.path)
582             ValidationIssueCollector.appendException(
583                 ValidationError(message=err_msg))
584             return False
585
586         # validate that 'Entry-Definitions' property exists in TOSCA.meta
587         data = self.zfile.read('TOSCA-Metadata/TOSCA.meta')
588         invalid_yaml_err_msg = (_('The file "TOSCA-Metadata/TOSCA.meta" in '
589                                   'the CSAR "%s" does not contain valid YAML '
590                                   'content.') % self.path)
591         try:
592             meta = yaml.load(data)
593             if type(meta) is dict:
594                 self.metadata = meta
595             else:
596                 ValidationIssueCollector.appendException(
597                     ValidationError(message=invalid_yaml_err_msg))
598                 return False
599         except yaml.YAMLError:
600             ValidationIssueCollector.appendException(
601                 ValidationError(message=invalid_yaml_err_msg))
602             return False
603
604         if 'Entry-Definitions' not in self.metadata:
605             err_msg = (_('The CSAR "%s" is missing the required metadata '
606                          '"Entry-Definitions" in '
607                          '"TOSCA-Metadata/TOSCA.meta".')
608                        % self.path)
609             ValidationIssueCollector.appendException(
610                 ValidationError(message=err_msg))
611             return False
612
613         # validate that 'Entry-Definitions' metadata value points to an
614         # existing file in the CSAR
615         entry = self.metadata.get('Entry-Definitions')
616         if entry and entry not in filelist:
617             err_msg = (_('The "Entry-Definitions" file defined in the '
618                          'CSAR "%s" does not exist.') % self.path)
619             ValidationIssueCollector.appendException(
620                 ValidationError(message=err_msg))
621             return False
622
623         # validate that external references in the main template actually
624         # exist and are accessible
625         self._validate_external_references()
626         return not self.error_caught
627
628     def get_metadata(self):
629         """Return the metadata dictionary."""
630
631         # validate the csar if not already validated
632         if not self.is_validated:
633             self.validate()
634
635         # return a copy to avoid changes overwrite the original
636         return dict(self.metadata) if self.metadata else None
637
638     def _get_metadata(self, key):
639         if not self.is_validated:
640             self.validate()
641         return self.metadata.get(key)
642
643     def get_author(self):
644         return self._get_metadata('Created-By')
645
646     def get_version(self):
647         return self._get_metadata('CSAR-Version')
648
649     def get_main_template(self):
650         entry_def = self._get_metadata('Entry-Definitions')
651         if entry_def in self.zfile.namelist():
652             return entry_def
653
654     def get_main_template_yaml(self):
655         main_template = self.get_main_template()
656         if main_template:
657             data = self.zfile.read(main_template)
658             invalid_tosca_yaml_err_msg = (
659                 _('The file "%(template)s" in the CSAR "%(csar)s" does not '
660                   'contain valid TOSCA YAML content.') %
661                 {'template': main_template, 'csar': self.path})
662             try:
663                 tosca_yaml = yaml.load(data)
664                 if type(tosca_yaml) is not dict:
665                     ValidationIssueCollector.appendException(
666                         ValidationError(message=invalid_tosca_yaml_err_msg))
667                 return tosca_yaml
668             except Exception:
669                 ValidationIssueCollector.appendException(
670                     ValidationError(message=invalid_tosca_yaml_err_msg))
671
672     def get_description(self):
673         desc = self._get_metadata('Description')
674         if desc is not None:
675             return desc
676
677         self.metadata['Description'] = \
678             self.get_main_template_yaml().get('description')
679         return self.metadata['Description']
680
681     def decompress(self):
682         if not self.is_validated:
683             self.validate()
684         self.temp_dir = tempfile.NamedTemporaryFile().name
685         with zipfile.ZipFile(self.csar, "r") as zf:
686             zf.extractall(self.temp_dir)
687
688     def _validate_external_references(self):
689         """Extracts files referenced in the main template
690
691         These references are currently supported:
692         * imports
693         * interface implementations
694         * artifacts
695         """
696         try:
697             self.decompress()
698             main_tpl_file = self.get_main_template()
699             if not main_tpl_file:
700                 return
701             main_tpl = self.get_main_template_yaml()
702
703             if 'imports' in main_tpl:
704                 ImportsLoader(main_tpl['imports'],
705                               os.path.join(self.temp_dir, main_tpl_file))
706
707             if 'topology_template' in main_tpl:
708                 topology_template = main_tpl['topology_template']
709
710                 if 'node_templates' in topology_template:
711                     node_templates = topology_template['node_templates']
712
713                     for node_template_key in node_templates:
714                         node_template = node_templates[node_template_key]
715                         if 'artifacts' in node_template:
716                             artifacts = node_template['artifacts']
717                             for artifact_key in artifacts:
718                                 artifact = artifacts[artifact_key]
719                                 if isinstance(artifact, six.string_types):
720                                     self._validate_external_reference(
721                                         main_tpl_file,
722                                         artifact)
723                                 elif isinstance(artifact, dict):
724                                     if 'file' in artifact:
725                                         self._validate_external_reference(
726                                             main_tpl_file,
727                                             artifact['file'])
728                                 else:
729                                     ValidationIssueCollector.appendException(
730                                         ValueError(_('Unexpected artifact '
731                                                      'definition for "%s".')
732                                                    % artifact_key))
733                                     self.error_caught = True
734                         if 'interfaces' in node_template:
735                             interfaces = node_template['interfaces']
736                             for interface_key in interfaces:
737                                 interface = interfaces[interface_key]
738                                 for opertation_key in interface:
739                                     operation = interface[opertation_key]
740                                     if isinstance(operation, six.string_types):
741                                         self._validate_external_reference(
742                                             main_tpl_file,
743                                             operation,
744                                             False)
745                                     elif isinstance(operation, dict):
746                                         if 'implementation' in operation:
747                                             self._validate_external_reference(
748                                                 main_tpl_file,
749                                                 operation['implementation'])
750         finally:
751             if self.temp_dir:
752                 shutil.rmtree(self.temp_dir)
753
754     def _validate_external_reference(self, tpl_file, resource_file,
755                                      raise_exc=True):
756         """Verify that the external resource exists
757
758         If resource_file is a URL verify that the URL is valid.
759         If resource_file is a relative path verify that the path is valid
760         considering base folder (self.temp_dir) and tpl_file.
761         Note that in a CSAR resource_file cannot be an absolute path.
762         """
763         if UrlUtils.validate_url(resource_file):
764             msg = (_('The resource at "%s" cannot be accessed.') %
765                    resource_file)
766             try:
767                 if UrlUtils.url_accessible(resource_file):
768                     return
769                 else:
770                     ValidationIssueCollector.appendException(
771                         URLException(what=msg))
772                     self.error_caught = True
773             except Exception:
774                 ValidationIssueCollector.appendException(
775                     URLException(what=msg))
776                 self.error_caught = True
777
778         if os.path.isfile(os.path.join(self.temp_dir,
779                                        os.path.dirname(tpl_file),
780                                        resource_file)):
781             return
782
783         if raise_exc:
784             ValidationIssueCollector.appendException(
785                 ValueError(_('The resource "%s" does not exist.')
786                            % resource_file))
787             self.error_caught = True
788 */
789
790