Exemplo n.º 1
0
    def parse(cls, contents: str) -> "CsarMeta":
        # FIXME: the meta format is not yaml, but it"s close enough to parse a simple file
        parsed = yaml.safe_load(contents)

        for req in CsarMeta.REQUIRED_KEYS:
            if req not in parsed:
                raise ParseError("Missing required meta entry: {}".format(req),
                                 CsarMeta.METADATA_PATH)

        csar_version = str(parsed[CsarMeta.KEY_CSAR_VERSION])
        if csar_version not in CsarMeta.SUPPORTED_CSAR_VERSIONS:
            raise ParseError(
                "{} {} is not supported. Supported versions: {}\".".format(
                    CsarMeta.KEY_CSAR_VERSION, csar_version,
                    CsarMeta.SUPPORTED_CSAR_VERSIONS), CsarMeta.METADATA_PATH)

        tmf_version = str(parsed[CsarMeta.KEY_TOSCA_META_FILE_VERSION])
        if tmf_version not in CsarMeta.SUPPORTED_META_FILE_VERSIONS:
            raise ParseError(
                "{} {} is not supported. Supported versions: {}\".".format(
                    CsarMeta.KEY_TOSCA_META_FILE_VERSION, tmf_version,
                    CsarMeta.SUPPORTED_META_FILE_VERSIONS),
                CsarMeta.METADATA_PATH)

        result = CsarMeta(
            name=parsed.get(CsarMeta.KEY_NAME),
            content_type=parsed.get(CsarMeta.KEY_CONTENT_TYPE),
            tosca_meta_file_version=tmf_version,
            csar_version=csar_version,
            created_by=parsed[CsarMeta.KEY_CREATED_BY],
            entry_definitions=parsed.get(CsarMeta.KEY_ENTRY_DEFINITIONS),
        )

        return result
Exemplo n.º 2
0
def _get_tosca_version(input_yaml):
    for k, v in input_yaml.value.items():
        if k.value == "tosca_definitions_version":
            try:
                return SUPPORTED_VERSIONS[v.value]
            except (TypeError, KeyError) as e:
                raise ParseError(f"Invalid TOSCA version. Available: {', '.join(SUPPORTED_VERSIONS.keys())}.",
                                 v.loc) from e

    raise ParseError("Missing TOSCA version", input_yaml.loc)
Exemplo n.º 3
0
    def parse(self, yaml_node):
        if not isinstance(yaml_node.value, list):
            raise ParseError("Expected list of single-key maps.",
                             yaml_node.loc)

        data = collections.OrderedDict()
        for item in yaml_node.value:
            if not isinstance(item.value, dict) or len(item.value) != 1:
                raise ParseError("Expected single-key map.", item.loc)
            (k, v), = item.value.items()
            data[k] = v
        return super().parse(Node(data, yaml_node.loc))
Exemplo n.º 4
0
    def parse(self, yaml_node):
        if not isinstance(yaml_node.value, dict):
            raise ParseError("Expected map.", yaml_node.loc)

        for k in yaml_node.value:
            if not isinstance(k.value, str):
                ParseError("Expected string key.", k.loc)

        return MapWrapper(
            collections.OrderedDict((k.value, self.value_class.parse(v))
                                    for k, v in yaml_node.value.items()),
            yaml_node.loc)
Exemplo n.º 5
0
    def validate_csar(self):
        with TemporaryDirectory(dir=self._csar_folder_path) as tempdir:
            ZipFile(self._csar_name, 'r').extractall(tempdir)

            try:
                meta_file_path = Path(
                    tempdir) / "TOSCA-Metadata" / "TOSCA.meta"
                if meta_file_path.exists():
                    with meta_file_path.open() as meta_file:
                        self._tosca_meta = yaml.safe_load(meta_file)

                    self._validate_csar_version()
                    self._validate_tosca_meta_file_version()
                    template_entry = self._get_entry_definitions()
                    self._get_created_by()
                    self._get_other_definitions()

                    # check if 'Entry-Definitions' points to an existing
                    # template file in the CSAR
                    if not Path(tempdir).joinpath(template_entry).exists():
                        raise ParseError(
                            'The file "{}" defined within "Entry-Definitions" '
                            'in "TOSCA-Metadata/TOSCA.meta" does not exist.'.
                            format(template_entry), self)

                    return template_entry
                else:
                    root_yaml_files = []

                    root_yaml_files.extend(Path(tempdir).glob('*.yaml'))
                    root_yaml_files.extend(Path(tempdir).glob('*.yml'))

                    if len(root_yaml_files) != 1:
                        raise ParseError(
                            "There should be one root level yaml "
                            "file in the root of the CSAR: {}.".format(
                                root_yaml_files), self)

                    with Path(root_yaml_files[0]).open() as root_template:
                        root_yaml_template = yaml.safe_load(root_template)
                        self._metadata = root_yaml_template.get('metadata')

                    self._get_template_version()
                    self._get_template_name()
                    self._get_author()

                    return root_yaml_files[0].name
            except Exception as e:
                raise ParseError("Invalid CSAR structure: {}".format(e), self)
Exemplo n.º 6
0
    def parse(self, yaml_node):
        if not isinstance(yaml_node.value, list):
            raise ParseError("Expected list.", yaml_node.loc)

        return ListWrapper(
            [self.value_class.parse(v) for v in yaml_node.value],
            yaml_node.loc)
Exemplo n.º 7
0
 def _get_entry_definitions(self):
     if 'Entry-Definitions' not in self._tosca_meta:
         raise ParseError(
             'The CSAR "{}" is missing the required metadata '
             '"Entry-Definitions" in "TOSCA-Metadata/TOSCA.meta".'.format(
                 self._csar_name), self)
     return self._tosca_meta.get('Entry-Definitions')
Exemplo n.º 8
0
def load(base_path, template_name):
    with (base_path / template_name).open() as input_fd:
        input_yaml = yaml.load(input_fd, str(template_name))
    if not isinstance(input_yaml.value, dict):
        raise ParseError(
            "Top level structure should be a map.",
            yaml_node.loc,
        )

    tosca_version = _get_tosca_version(input_yaml)
    parser = _get_parser(tosca_version)

    stdlib_yaml = stdlib.load(tosca_version)
    service = parser.parse(
        stdlib_yaml,
        base_path,
        PurePath("STDLIB"),
        set(),
    )[0]
    service.merge(
        parser.parse(
            input_yaml,
            base_path,
            template_name,
            set(),
        )[0])
    service.visit("resolve_path", base_path)
    service.visit("resolve_reference", service)

    return service
Exemplo n.º 9
0
    def parse(cls, contents: str) -> "ServiceTemplateMeta":
        parsed = yaml.safe_load(contents)

        if "metadata" not in parsed:
            raise ParseError("Missing required service template metadata.", "")

        for req in ServiceTemplateMeta.REQUIRED_KEYS:
            if req not in parsed["metadata"]:
                raise ParseError(
                    "Missing required service template meta entry: metadata. {}"
                    .format(req), "")

        return ServiceTemplateMeta(
            name=parsed["metadata"][ServiceTemplateMeta.KEY_NAME],
            author=parsed["metadata"].get(ServiceTemplateMeta.KEY_AUTHOR),
            version=parsed["metadata"][ServiceTemplateMeta.KEY_VERSION],
        )
Exemplo n.º 10
0
 def _validate_csar_version(self):
     csar_version = self._tosca_meta.get('CSAR-Version')
     if csar_version and csar_version != 1.1:
         raise ParseError(
             'CSAR-Version entry in the CSAR {} is '
             'required to denote version 1.1".'.format(self._csar_name),
             self)
     return csar_version
Exemplo n.º 11
0
 def _validate_tosca_meta_file_version(self):
     tosca_meta_file_version = self._tosca_meta.get(
         'TOSCA-Meta-File-Version')
     if tosca_meta_file_version and tosca_meta_file_version != 1.1:
         raise ParseError(
             'TOSCA-Meta-File-Version entry in the CSAR {} is '
             'required to denote version 1.1".'.format(self._csar_name),
             self)
     return tosca_meta_file_version
Exemplo n.º 12
0
 def abort(cls, msg, loc=None):
     raise ParseError(f"[{cls.__name__}] {msg}", loc)
Exemplo n.º 13
0
 def abort(cls, msg, loc=None):
     raise ParseError("[{}] {}".format(cls.__name__, msg), loc)
Exemplo n.º 14
0
    def package_csar(self,
                     output_file: str,
                     service_template: str = None,
                     csar_format: str = "zip") -> str:
        meta = self.parse_csar_meta()

        try:
            if not service_template:
                root_yaml_files = self.get_root_yaml_files()

                if meta is None and len(root_yaml_files) != 1:
                    raise ParseError(
                        "You didn't specify the CSAR TOSCA entrypoint with '-t/--service-template' "
                        "option. Therefore there should be one YAML file in the root of the CSAR to "
                        "select it as the entrypoint. More than one YAML has been found: {}. Please "
                        "select one of the files as the CSAR entrypoint using '-t/--service-template' "
                        "flag or remove all the excessive YAML files.".format(
                            list(map(str, root_yaml_files))), self)
                service_template = root_yaml_files[0].name
            else:
                if not self._member_exists(PurePath(service_template)):
                    raise ParseError(
                        "The supplied TOSCA service template file '{}' does not exist in folder '{}'."
                        .format(service_template, self.csar_dir), self)

            meta = self.parse_csar_meta()
            if meta is not None:

                template_entry = meta.entry_definitions
                if service_template and template_entry != service_template:
                    raise ParseError(
                        "The file entry '{}' defined within 'Entry-Definitions' in "
                        "'TOSCA-Metadata/TOSCA.meta' does not match with the file name '{}' supplied "
                        "in service_template CLI argument.".format(
                            template_entry, service_template), self)

                # check if "Entry-Definitions" points to an existing
                # template file in the CSAR
                if template_entry is not None and not self._member_exists(
                        PurePath(template_entry)):
                    raise ParseError(
                        "The file '{}' defined within 'Entry-Definitions' in 'TOSCA-Metadata/TOSCA.meta' "
                        "does not exist.".format(template_entry), self)
                return shutil.make_archive(output_file, csar_format,
                                           self.csar_dir)
            else:
                with TemporaryDirectory(prefix="opera-package-") as tempdir:
                    extract_path = Path(tempdir) / "extract"
                    shutil.copytree(self.csar_dir, extract_path)

                    # create TOSCA-Metadata/TOSCA.meta file using the specified
                    # TOSCA service template or directory root YAML file
                    content = (
                        "TOSCA-Meta-File-Version: 1.1\n"
                        "CSAR-Version: 1.1\n"
                        "Created-By: xOpera TOSCA orchestrator\n"
                        "Entry-Definitions: {}\n").format(service_template)

                    meta_file_folder = extract_path / "TOSCA-Metadata"
                    meta_file = (meta_file_folder / "TOSCA.meta")

                    meta_file_folder.mkdir()
                    meta_file.touch()
                    meta_file.write_text(content)

                    return shutil.make_archive(output_file, csar_format,
                                               extract_path)
        except Exception as e:  # noqa: W0703
            raise ParseError(
                "Error creating CSAR:\n{}".format(traceback.format_exc()),
                self) from e
Exemplo n.º 15
0
 def _get_template_name(self):
     if "template_version" not in self._metadata:
         raise ParseError(
             'The CSAR "{}" is missing the required '
             'template_name in metadata".'.format(self._csar_name), self)
     return self._metadata.get('template_name')