framework for checking vnf requirement 39/63439/1
authorLianhao Lu <lianhao.lu@intel.com>
Wed, 29 Aug 2018 10:17:46 +0000 (18:17 +0800)
committerLianhao Lu <lianhao.lu@intel.com>
Wed, 29 Aug 2018 10:37:48 +0000 (18:37 +0800)
Implemented the internal code framework to add test cases to check vnf
requirements. Use command line parameter '--test-reqs' with the list of
vnf requirment IDs to invoke 'vnfsdk csar-validate'.

Also implement test case for R-66070: csar manifest metadata

Change-Id: I385e515f3e87f1e89fb7baf9ec3e0560f44541cd
Issue-ID: VNFSDK-316
Issue-ID: VNFSDK-174
Signed-off-by: Lianhao Lu <lianhao.lu@intel.com>
requirements.txt
setup.py
tests/vnfreq/test_pkg_reqs.py [new file with mode: 0644]
tests/vnfreq/test_vnfreq.py [new file with mode: 0644]
vnfsdk_pkgtools/cli/__main__.py
vnfsdk_pkgtools/validator/__init__.py
vnfsdk_pkgtools/vnfreq/__init__.py [new file with mode: 0644]
vnfsdk_pkgtools/vnfreq/pkg_reqs.py [new file with mode: 0644]

index dbc2a26..fa17a3e 100644 (file)
@@ -3,3 +3,4 @@ requests>=2.3.0
 stevedore>=1.9.0
 udatetime<1.0,>=0.0.16
 nfv-toscaparser<2.0,>=1.0.1
+prettytable<1.0
index 21cad65..cba146a 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -85,7 +85,10 @@ setup(
             'vnfsdk = vnfsdk_pkgtools.cli.__main__:main'],
         'vnfsdk.pkgtools.validator': [
             'toscaparser = vnfsdk_pkgtools.validator.toscaparser_validator:ToscaparserValidator',
-        ]
+        ],
+        'vnfsdk.pkgtools.vnfreq': [
+            'R-66070 = vnfsdk_pkgtools.vnfreq.pkg_reqs:R66070',
+        ],
     },
 
     include_package_data=True,
diff --git a/tests/vnfreq/test_pkg_reqs.py b/tests/vnfreq/test_pkg_reqs.py
new file mode 100644 (file)
index 0000000..b712212
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright (c) 2018 Intel Corp. All rights reserved.
+#
+# 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.
+#
+
+import pytest
+
+from vnfsdk_pkgtools import vnfreq
+
+def test_R66070_fail(mocker):
+    reader = mocker.Mock()
+    reader.manifest = None
+
+    tester = vnfreq.get_vnfreq_tester("R-66070")
+    tester.check(reader, None)
+    assert isinstance(tester.err, vnfreq.VnfRequirementError)
+
diff --git a/tests/vnfreq/test_vnfreq.py b/tests/vnfreq/test_vnfreq.py
new file mode 100644 (file)
index 0000000..03404fc
--- /dev/null
@@ -0,0 +1,34 @@
+# Copyright (c) 2018 Intel Corp. All rights reserved.
+#
+# 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.
+#
+
+import pytest
+
+from vnfsdk_pkgtools import vnfreq
+
+class FakeTester(vnfreq.TesterBase):
+    ID = 'fake'
+    DESC = 'fake'
+
+    def __init__(self, *args, **kwargs):
+        super(FakeTester, self).__init__()
+
+    def _do_check(self, reader, tosca):
+        return 'error'
+
+
+def test_check_and_print(mocker):
+    mocker.patch('vnfsdk_pkgtools.vnfreq.get_vnfreq_tester', new=FakeTester)
+    ret = vnfreq.check_and_print(['fake'], mocker.Mock(), mocker.Mock())
+    assert ret == 1
index 2b262b9..09896e0 100644 (file)
@@ -14,7 +14,6 @@
 # under the License.
 #
 
-from vnfsdk_pkgtools.packager import csar
 import sys
 import logging
 import argparse
@@ -22,7 +21,12 @@ import os
 import shutil
 import tempfile
 
+import pkg_resources
+
+from vnfsdk_pkgtools.packager import csar
 from vnfsdk_pkgtools import validator
+from vnfsdk_pkgtools import vnfreq
+
 
 def csar_create_func(namespace):
 
@@ -39,13 +43,20 @@ def csar_open_func(namespace):
 def csar_validate_func(namespace):
     workdir = tempfile.mkdtemp()
     try:
-        reader = None
+        err = 0
         reader = csar.read(namespace.source,
                            workdir,
                            no_verify_cert=True)
 
         driver = validator.get_validator(namespace.parser)
         driver.validate(reader)
+        print("---Basic & HPA validation passed!---")
+        if namespace.test_reqs:
+            print("---Check VNF Requirements---")
+            err = vnfreq.check_and_print(namespace.test_reqs,
+                                         reader,
+                                         driver)
+        return err
     finally:
         shutil.rmtree(workdir, ignore_errors=True)
 
@@ -121,7 +132,14 @@ def parse_args(args_list):
     csar_validate.add_argument(
         '-p', '--parser',
         default='toscaparser',
+        choices=[ep.name for ep in pkg_resources.iter_entry_points(validator.NS)],
         help='use which csar parser to validate')
+    csar_validate.add_argument(
+        '--test-reqs',
+        nargs='*',
+        default=[],
+        choices=[ep.name for ep in pkg_resources.iter_entry_points(vnfreq.NS)],
+        help='list of the ID of VNF Requirements to check, i.e. R-66070')
 
     return parser.parse_args(args_list)
 
@@ -141,7 +159,7 @@ def init_logging(args):
 def main():
     args = parse_args(sys.argv[1:])
     init_logging(args)
-    args.func(args)
+    return args.func(args)
 
 
 if __name__ == '__main__':
index 730acf6..c072543 100644 (file)
@@ -19,7 +19,7 @@ import six
 from stevedore import driver
 
 
-VALIDATOR_NS = "vnfsdk.pkgtools.validator"
+NS = "vnfsdk.pkgtools.validator"
 
 def get_validator(params):
     """Get validate driver and load it.
@@ -27,7 +27,7 @@ def get_validator(params):
     :param params: parameters to decide which validator to load
     """
 
-    loaded_driver = driver.DriverManager(VALIDATOR_NS,
+    loaded_driver = driver.DriverManager(NS,
                                          params,
                                          invoke_on_load=True)
     return loaded_driver.driver
diff --git a/vnfsdk_pkgtools/vnfreq/__init__.py b/vnfsdk_pkgtools/vnfreq/__init__.py
new file mode 100644 (file)
index 0000000..376b519
--- /dev/null
@@ -0,0 +1,90 @@
+# Copyright (c) 2018 Intel Corp. All rights reserved.
+#
+# 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.
+#
+
+import abc
+import textwrap
+
+import prettytable
+import six
+from stevedore import driver
+
+
+NS = "vnfsdk.pkgtools.vnfreq"
+
+def get_vnfreq_tester(name):
+    """Get vnf requirement tester.
+
+    :param name: name of the vnf requirement tester
+    """
+
+    loaded_driver = driver.DriverManager(NS,
+                                         name,
+                                         invoke_on_load=True)
+    return loaded_driver.driver
+
+
+def check_and_print(test_reqs, reader, tosca):
+    err = 0
+
+    table = prettytable.PrettyTable(['Req ID', 'Status', 'Description'])
+    table.align = 'l'
+    for t in test_reqs:
+        testor = get_vnfreq_tester(t)
+        testor.check(reader, tosca)
+        if testor.err:
+            status = 'ERROR: ' + str(testor.err)
+            err = 1
+        else:
+            status = 'OK'
+        # wrap the testor description because it's too long
+        lines = textwrap.wrap(testor.DESC, width=40)
+        table.add_row([testor.ID, status, lines.pop(0)])
+        for line in lines:
+            table.add_row(['','',line])
+    if test_reqs:
+        print(table)
+    return err
+
+
+class VnfRequirementError(ValueError):
+    pass
+
+
+@six.add_metaclass(abc.ABCMeta)
+class TesterBase(object):
+    """Base class for vnf requirement tester."""
+
+    ID = None
+    DESC = None
+
+    def __init__(self):
+        self.err = None
+
+    @abc.abstractmethod
+    def _do_check(self, reader, tosca):
+        """Check the vnf requirement meet or not.
+
+        :param reader: instance of package.csar._CSARReader
+        :param tosca: instance of validator.toscaparser_validator.ToscaparserValidator
+
+        return: 0 for success, otherwise failure
+        """
+
+    def check(self, reader, tosca):
+        try:
+            self.err = self._do_check(reader, tosca)
+        except Exception as e:
+            self.err = e
+
diff --git a/vnfsdk_pkgtools/vnfreq/pkg_reqs.py b/vnfsdk_pkgtools/vnfreq/pkg_reqs.py
new file mode 100644 (file)
index 0000000..c5b20f7
--- /dev/null
@@ -0,0 +1,37 @@
+# Copyright (c) 2018 Intel Corp. All rights reserved.
+#
+# 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.
+#
+
+import abc
+
+import six
+from stevedore import driver
+
+from vnfsdk_pkgtools import vnfreq
+
+
+class R66070(vnfreq.TesterBase):
+    ID = "R-66070"
+    DESC = ("The VNF Package MUST include VNF Identification Data to "
+            "uniquely identify the resource for a given VNF provider. "
+            "The identification data must include: an identifier for "
+            "the VNF, the name of the VNF as was given by the VNF "
+            "provider, VNF description, VNF provider, and version.")
+
+    def _do_check(self, reader, tosca):
+        if not reader.manifest:
+            raise vnfreq.VnfRequirementError("No manifest file found")
+        # Existing reader.manifest already means a valid manifest file
+        # no futher check needed.
+        return 0