From 7e6f0982944bed3ea6fc1a93889700c557406f2d Mon Sep 17 00:00:00 2001 From: Nandini Date: Wed, 6 Apr 2016 09:55:22 +0530 Subject: [PATCH] Added support for Repositories Implemented repositories section in tosca template and validated the fields. Change-Id: Ib629020cd0099c6620b80c1a7de20adf56532f0c Partially-Implements: blueprint tosca-repository --- toscaparser/imports.py | 8 +- toscaparser/repositories.py | 52 +++++++++ .../data/test_repositories_definition.yaml | 6 +- .../tosca_repositories_test_definition.yaml | 26 +++++ toscaparser/tests/test_toscatpl.py | 18 ++- toscaparser/tests/test_toscatplvalidation.py | 109 +++++++++++++++++- toscaparser/tosca_template.py | 11 ++ 7 files changed, 222 insertions(+), 8 deletions(-) create mode 100644 toscaparser/repositories.py create mode 100644 toscaparser/tests/data/tosca_repositories_test_definition.yaml diff --git a/toscaparser/imports.py b/toscaparser/imports.py index 5149382b..789a5440 100644 --- a/toscaparser/imports.py +++ b/toscaparser/imports.py @@ -14,6 +14,7 @@ import logging import os from toscaparser.common.exception import ExceptionCollector +from toscaparser.common.exception import InvalidPropertyValueError from toscaparser.common.exception import MissingRequiredFieldError from toscaparser.common.exception import UnknownFieldError from toscaparser.common.exception import ValidationError @@ -150,12 +151,17 @@ class ImportsLoader(object): | URL | URL | OK | +----------+--------+------------------------------+ """ - short_import_notation = False if isinstance(import_uri_def, dict): self._validate_import_keys(import_name, import_uri_def) file_name = import_uri_def.get(self.FILE) repository = import_uri_def.get(self.REPOSITORY) + repos = self.repositories.keys() + if repository is not None: + if repository not in repos: + ExceptionCollector.appendException( + InvalidPropertyValueError( + what=_('Repository is not found in "%s"') % repos)) else: file_name = import_uri_def repository = None diff --git a/toscaparser/repositories.py b/toscaparser/repositories.py new file mode 100644 index 00000000..184eba43 --- /dev/null +++ b/toscaparser/repositories.py @@ -0,0 +1,52 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from toscaparser.common.exception import ExceptionCollector +from toscaparser.common.exception import MissingRequiredFieldError +from toscaparser.common.exception import UnknownFieldError +from toscaparser.common.exception import URLException +from toscaparser.utils.gettextutils import _ +import toscaparser.utils.urlutils + +SECTIONS = (DESCRIPTION, URL, CREDENTIAL) = \ + ('description', 'url', 'credential') + + +class Repository(object): + def __init__(self, repositories, values): + self.name = repositories + self.reposit = values + if isinstance(self.reposit, dict): + if 'url' not in self.reposit.keys(): + ExceptionCollector.appendException( + MissingRequiredFieldError(what=_('Repository "%s"') + % self.name, required='url')) + self.url = self.reposit['url'] + self.load_and_validate(self.name, self.reposit) + + def load_and_validate(self, val, reposit_def): + self.keyname = val + if isinstance(reposit_def, dict): + for key in reposit_def.keys(): + if key not in SECTIONS: + ExceptionCollector.appendException( + UnknownFieldError(what=_('repositories "%s"') + % self.keyname, field=key)) + + if URL in reposit_def.keys(): + reposit_url = reposit_def.get(URL) + url_val = toscaparser.utils.urlutils.UrlUtils.\ + validate_url(reposit_url) + if url_val is not True: + ExceptionCollector.appendException( + URLException(what=_('repsositories "%s" Invalid Url') + % self.keyname)) diff --git a/toscaparser/tests/data/test_repositories_definition.yaml b/toscaparser/tests/data/test_repositories_definition.yaml index 2145d8f1..c2856c8f 100644 --- a/toscaparser/tests/data/test_repositories_definition.yaml +++ b/toscaparser/tests/data/test_repositories_definition.yaml @@ -4,9 +4,9 @@ repositories: some_repository: description: Some repo url: https://raw.githubusercontent.com/openstack/tosca-parser/master/toscaparser/tests/data/custom_types/ - namespace_uri: http://docs.oasis-open.org/tosca/ns/simple/yaml/1.0a - namespace_prefix: oasis_tosca - + credential: #type: Credential + token_type: basic_auth + token: myusername:mypassword imports: - some_import: file: compute_with_prop.yaml diff --git a/toscaparser/tests/data/tosca_repositories_test_definition.yaml b/toscaparser/tests/data/tosca_repositories_test_definition.yaml new file mode 100644 index 00000000..0001d062 --- /dev/null +++ b/toscaparser/tests/data/tosca_repositories_test_definition.yaml @@ -0,0 +1,26 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: TOSCA simple profile with repositories validation and imports. + +repositories: + repo_code0: https://raw.githubusercontent.com/nandinivemula/intern + repo_code1: + description: My project's code Repository in github usercontent. + url: https://raw.githubusercontent.com/nandinivemula/intern/master + credential: #type: Credential + token_type: basic_auth + token: myusername:mypassword + + repo_code2: + description: My Project's code Repository in github. + url: https://github.com/nandinivemula/intern/master + credential: #type: Credential + token_type: basic_auth + token: myusername:mypassword + +imports: + - sample_import: + file: tosca_repository_import.yaml + repository: repo_code1 + namespace_uri: https://github.com/nandinivemula/intern + namespace_prefix: intern diff --git a/toscaparser/tests/test_toscatpl.py b/toscaparser/tests/test_toscatpl.py index 3fd49bf8..22309103 100644 --- a/toscaparser/tests/test_toscatpl.py +++ b/toscaparser/tests/test_toscatpl.py @@ -12,7 +12,6 @@ import os import six - from toscaparser.common import exception import toscaparser.elements.interfaces as ifaces from toscaparser.elements.nodetype import NodeType @@ -26,16 +25,17 @@ import toscaparser.utils.yamlparser class ToscaTemplateTest(TestCase): - '''TOSCA template.''' tosca_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_single_instance_wordpress.yaml") tosca = ToscaTemplate(tosca_tpl) - tosca_elk_tpl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "data/tosca_elk.yaml") + tosca_repo_tpl = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "data/tosca_repositories_test_definition.yaml") def test_version(self): self.assertEqual(self.tosca.version, "tosca_simple_yaml_1_0") @@ -236,6 +236,18 @@ class ToscaTemplateTest(TestCase): expected_hosts, sorted([v.type for v in node_tpl.relationships.values()])) + def test_repositories(self): + template = ToscaTemplate(self.tosca_repo_tpl) + self.assertEqual( + ['repo_code0', 'repo_code1', 'repo_code2'], + sorted([input.name for input in template.repositories])) + + input_name = "repo_code2" + expected_url = "https://github.com/nandinivemula/intern/master" + for input in template.repositories: + if input.name == input_name: + self.assertEqual(input.url, expected_url) + def test_template_macro(self): template = ToscaTemplate(self.tosca_elk_tpl) for node_tpl in template.nodetemplates: diff --git a/toscaparser/tests/test_toscatplvalidation.py b/toscaparser/tests/test_toscatplvalidation.py index 81a1a6c4..6b48fcec 100644 --- a/toscaparser/tests/test_toscatplvalidation.py +++ b/toscaparser/tests/test_toscatplvalidation.py @@ -20,12 +20,12 @@ from toscaparser.parameters import Input from toscaparser.parameters import Output from toscaparser.policy import Policy from toscaparser.relationship_template import RelationshipTemplate +from toscaparser.repositories import Repository from toscaparser.tests.base import TestCase from toscaparser.topology_template import TopologyTemplate from toscaparser.tosca_template import ToscaTemplate from toscaparser.triggers import Triggers from toscaparser.utils.gettextutils import _ - import toscaparser.utils.yamlparser @@ -335,6 +335,113 @@ heat-translator/master/translator/tests/data/custom_types/wordpress.yaml 'to verify valid values.'), err.__str__()) + def _repo_content(self, path): + repositories = path['repositories'] + reposit = [] + for name, val in repositories.items(): + reposits = Repository(name, val) + reposit.append(reposits) + return reposit + + def test_repositories(self): + tpl_snippet = ''' + repositories: + repo_code0: https://raw.githubusercontent.com/nandinivemula/intern + repo_code1: + description: My project's code Repository in github usercontent. + url: https://github.com/nandinivemula/intern + credential: + user: nandini + password: tcs@12345 + repo_code2: + description: My Project's code Repository in github. + url: https://github.com/nandinivemula/intern + credential: + user: xyzw + password: xyz@123 + ''' + tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet)) + repoobject = self._repo_content(tpl) + actualrepo_names = [] + for repo in repoobject: + repos = repo.name + actualrepo_names.append(repos) + reposname = list(tpl.values()) + reposnames = reposname[0] + expected_reponames = list(reposnames.keys()) + self.assertEqual(expected_reponames, actualrepo_names) + + def test_repositories_with_missing_required_field(self): + tpl_snippet = ''' + repositories: + repo_code0: https://raw.githubusercontent.com/nandinivemula/intern + repo_code1: + description: My project's code Repository in github usercontent. + credential: + user: nandini + password: tcs@12345 + repo_code2: + description: My Project's code Repository in github. + url: https://github.com/nandinivemula/intern + credential: + user: xyzw + password: xyz@123 + ''' + tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet)) + err = self.assertRaises(exception.MissingRequiredFieldError, + self._repo_content, tpl) + expectedmessage = _('Repository "repo_code1" is missing ' + 'required field "url".') + self.assertEqual(expectedmessage, err.__str__()) + + def test_repositories_with_unknown_field(self): + tpl_snippet = ''' + repositories: + repo_code0: https://raw.githubusercontent.com/nandinivemula/intern + repo_code1: + description: My project's code Repository in github usercontent. + url: https://github.com/nandinivemula/intern + credential: + user: nandini + password: tcs@12345 + repo_code2: + descripton: My Project's code Repository in github. + url: https://github.com/nandinivemula/intern + credential: + user: xyzw + password: xyz@123 + ''' + tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet)) + err = self.assertRaises(exception.UnknownFieldError, + self._repo_content, tpl) + expectedmessage = _('repositories "repo_code2" contains unknown field' + ' "descripton". Refer to the definition to verify' + ' valid values.') + self.assertEqual(expectedmessage, err.__str__()) + + def test_repositories_with_invalid_url(self): + tpl_snippet = ''' + repositories: + repo_code0: https://raw.githubusercontent.com/nandinivemula/intern + repo_code1: + description: My project's code Repository in github usercontent. + url: h + credential: + user: nandini + password: tcs@12345 + repo_code2: + description: My Project's code Repository in github. + url: https://github.com/nandinivemula/intern + credential: + user: xyzw + password: xyz@123 + ''' + tpl = (toscaparser.utils.yamlparser.simple_parse(tpl_snippet)) + err = self.assertRaises(exception.URLException, + self._repo_content, tpl) + expectedmessage = _('repsositories "repo_code1" Invalid Url') + self.assertEqual(expectedmessage, err.__str__()) + def test_groups(self): tpl_snippet = ''' node_templates: diff --git a/toscaparser/tosca_template.py b/toscaparser/tosca_template.py index ba056da2..2a731825 100644 --- a/toscaparser/tosca_template.py +++ b/toscaparser/tosca_template.py @@ -23,6 +23,7 @@ from toscaparser.elements.entity_type import update_definitions from toscaparser.extensions.exttools import ExtTools import toscaparser.imports from toscaparser.prereq.csar import CSAR +from toscaparser.repositories import Repository from toscaparser.topology_template import TopologyTemplate from toscaparser.tpl_relationship_graph import ToscaGraph from toscaparser.utils.gettextutils import _ @@ -94,6 +95,7 @@ class ToscaTemplate(object): self.relationship_types = self._tpl_relationship_types() self.description = self._tpl_description() self.topology_template = self._topology_template() + self.repositories = self._tpl_repositories() if self.topology_template.tpl: self.inputs = self._inputs() self.relationship_templates = self._relationship_templates() @@ -133,6 +135,15 @@ class ToscaTemplate(object): def _tpl_imports(self): return self.tpl.get(IMPORTS) + def _tpl_repositories(self): + repositories = self.tpl.get(REPOSITORIES) + reposit = [] + if repositories: + for name, val in repositories.items(): + reposits = Repository(name, val) + reposit.append(reposits) + return reposit + def _tpl_relationship_types(self): return self._get_custom_types(RELATIONSHIP_TYPES)