From 0384b57fa175d45f5c3947adb488ef572669bce1 Mon Sep 17 00:00:00 2001 From: Michal Jagiello Date: Fri, 4 Feb 2022 14:00:57 +0000 Subject: Declare nested inputs in services Distinguish service and xNFs inputs in schema Add 'coverage' env in tox Issue-ID: INT-2060 Signed-off-by: Michal Jagiello Change-Id: I15c4ac2b2ddb28c938044b7e0a130a1644146f8b --- docs/source/schemas/version_1_1.rst | 37 +++++++++ .../resources/sdc_properties_mixins.py | 88 +++++++++++++++------- onap_data_provider/resources/xnf_resource.py | 2 +- onap_data_provider/schemas/infra_1_1.schema | 30 +++++++- requirements.txt | 2 +- setup.py | 2 +- tests/test_service_instance_resource.py | 20 ++--- tox.ini | 7 ++ 8 files changed, 145 insertions(+), 43 deletions(-) diff --git a/docs/source/schemas/version_1_1.rst b/docs/source/schemas/version_1_1.rst index cb78222..152e018 100644 --- a/docs/source/schemas/version_1_1.rst +++ b/docs/source/schemas/version_1_1.rst @@ -159,6 +159,10 @@ Service - List of `Service properties 1.1`_ - NO - + * - inputs + - List of `Service inputs 1.1`_ + - NO + - .. _Service resources 1.1: @@ -168,6 +172,39 @@ Service .. include:: /schemas/resources/shared/service_properties.rst +.. _Service inputs 1.1: + +Service inputs +^^^^^^^^^^^^^^ + +.. list-table:: + :header-rows: 1 + + * - Property + - Type + - Required + - Comment + * - name + - string + - YES + - + * - type + - string + - NO + - Required if new input is going to be declared + * - value + - string|boolean|number + - NO + - Required if a default value is going to be set + * - nested-input + - boolean + - NO + - Determines if nested input is going to be created + * - resource + - boolean + - NO + - Required if nested input is going to be created + PNF --- diff --git a/onap_data_provider/resources/sdc_properties_mixins.py b/onap_data_provider/resources/sdc_properties_mixins.py index 9a2b625..28d06c3 100644 --- a/onap_data_provider/resources/sdc_properties_mixins.py +++ b/onap_data_provider/resources/sdc_properties_mixins.py @@ -14,15 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. """ -from typing import Any, List, Union +import logging +from abc import ABC +from typing import Any, Dict, List, Union from onapsdk.exceptions import SDKException, ValidationError, ParameterError # type: ignore from onapsdk.sdc.component import Component # type: ignore -from onapsdk.sdc.properties import Property # type: ignore +from onapsdk.sdc.properties import NestedInput, Property # type: ignore from onapsdk.sdc.sdc_resource import SdcResource # type: ignore -class SdcPropertiesMixins: +class SdcPropertiesMixins(ABC): """Mixins class for properties handling. Mixin class for propoerties preparation for SdcResources and Components. @@ -66,20 +68,67 @@ class SdcPropertiesMixins: f"for resourceclass '{str(propresource.__class__.__name__)}' is not provided yet!" ) + def declare_input(self, propresource: Union[SdcResource, Component], property_data: Dict[str, Any]) -> None: + """Declare input. + + Method to get a property from a component and create an input for it. + + Args: + propresource (Union[SdcResource, Component]): Resource to create an input + property_data (Dict[str, Any]): Data used to create an input + + Raises: + ValidationError: Provided data is invalid - missing property type + ParameterError: Declaring input returns an SDC error + + """ + proptype = property_data.get("type") + if proptype is None: + raise ValidationError( + "New input '{0}' is missing a type!".format( + str(property_data["name"]) + ) + ) + + property = Property( + name=property_data["name"], + property_type=proptype, + value=property_data.get("value"), + ) + try: + propresource.add_property(property) + propresource.declare_input(property) + except SDKException: + raise ParameterError( + f"Creation of new input '{str(property_data['name'])}' is not provided yet!" + ) + + def declare_nested_input(self, propresource: Union[SdcResource, Component], data: Dict[str, Any]) -> None: + """Declare nested input. + + Args: + propresource (SdcResource): Resource for which nested input is going to be declared + data (Dict[str, Any]): Data used for input creation. + """ + if not isinstance(propresource, SdcResource): + logging.error("Can't declare nested inputs for components!") + return + comp: Component = propresource.get_component_by_name(data["resource"]) + propresource.declare_input(NestedInput(comp.sdc_resource, comp.sdc_resource.get_input(data["name"]))) + def set_inputs( - self, propresource: Union[SdcResource, Component], data: List[Any] + self, propresource: Union[SdcResource, Component], data: List[Dict[str, Any]] ) -> None: """Set inputs of an SdcResource. Args: sdcresource (SdcResource): the SdcResource the inputs should belong to data (Dict[str, Any]): Data needed to create resource. - - Raises ValidationError """ - for property_data in data: - - if any( + for property_data in data: # type: Dict[str, Any] + if property_data.get("nested-input"): + self.declare_nested_input(propresource, property_data) + elif any( (prop.name == property_data["name"] for prop in propresource.inputs) ): propresource.set_input_default_value( @@ -87,23 +136,4 @@ class SdcPropertiesMixins: property_data.get("value"), ) else: - proptype = property_data.get("type") - if proptype is None: - raise ValidationError( - "New input '{0}' is missing a type!".format( - str(property_data["name"]) - ) - ) - - property = Property( - name=property_data["name"], - property_type=proptype, - value=property_data.get("value"), - ) - try: - propresource.add_property(property) - propresource.declare_input(property) - except SDKException: - raise ParameterError( - f"Creation of new input '{str(property_data['name'])}' is not provided yet!" - ) + self.declare_input(propresource, property_data) diff --git a/onap_data_provider/resources/xnf_resource.py b/onap_data_provider/resources/xnf_resource.py index efede03..63b01dc 100644 --- a/onap_data_provider/resources/xnf_resource.py +++ b/onap_data_provider/resources/xnf_resource.py @@ -24,7 +24,7 @@ from onapsdk.sdc.properties import Property # type: ignore from .sdc_properties_mixins import SdcPropertiesMixins -class XnfResource(ABC, SdcPropertiesMixins): +class XnfResource(SdcPropertiesMixins, ABC): """Xnf resource class. Network function base class. diff --git a/onap_data_provider/schemas/infra_1_1.schema b/onap_data_provider/schemas/infra_1_1.schema index 7514acc..063e78a 100644 --- a/onap_data_provider/schemas/infra_1_1.schema +++ b/onap_data_provider/schemas/infra_1_1.schema @@ -281,7 +281,35 @@ properties: - required: - name - value - inputs: *props + inputs: &inputs + type: array + items: + type: object + properties: + name: + type: string + type: + type: string + nested-input: + type: boolean + resource: + type: string + value: + type: + - string + - number + - boolean + anyOf: + - required: + - name + - type + - required: + - name + - value + - required: + - name + - nested-input + - resource required: - name required: diff --git a/requirements.txt b/requirements.txt index ef61bd0..2a85652 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -onapsdk==9.2.2 +onapsdk==9.3.0 PyYAML~=5.4.1 jsonschema==3.2.0 diff --git a/setup.py b/setup.py index 6bb365e..42e8334 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ setuptools.setup( "onap-data-provider=onap_data_provider.data_provider:run", ] }, - install_requires=["onapsdk==9.2.2", "PyYAML~=5.4.1", "jsonschema==3.2.0"], + install_requires=["onapsdk==9.3.0", "PyYAML~=5.4.1", "jsonschema==3.2.0"], classifiers=[ "Development Status :: 5 - Production/Stable", "Programming Language :: Python", diff --git a/tests/test_service_instance_resource.py b/tests/test_service_instance_resource.py index 04a18d6..91e8860 100644 --- a/tests/test_service_instance_resource.py +++ b/tests/test_service_instance_resource.py @@ -128,20 +128,20 @@ def test_si_resource_create( mock_service_instantionation.instantiate_macro.assert_called_once() -def test_so_service(): +@patch("onap_data_provider.resources.service_instance_resource.ServiceInstanceResource.service_subscription", new_callable=PropertyMock) +def test_so_service(mock_service_subscription): si_resource = ServiceInstanceResource(INSTANTIATION_PARAMETERS_DATA) so_service = si_resource.so_service - assert so_service.subscription_service_type == "service1" assert len(so_service.vnfs) == 1 vnf = so_service.vnfs[0] - assert vnf["model_name"] == "test" - assert vnf["vnf_name"] == "test" - assert len(vnf["parameters"]) == 2 - assert len(vnf["vf_modules"]) == 1 - vf_module = vnf["vf_modules"][0] - assert vf_module["model_name"] == "base_ubuntu20" - assert vf_module["vf_module_name"] == "base_ubuntu20" - assert len(vf_module["parameters"]) == 10 + assert vnf.model_name == "test" + assert vnf.instance_name == "test" + assert len(vnf.parameters) == 2 + assert len(vnf.vf_modules) == 1 + vf_module = vnf.vf_modules[0] + assert vf_module.model_name == "base_ubuntu20" + assert vf_module.instance_name == "base_ubuntu20" + assert len(vf_module.parameters) == 10 @patch("onap_data_provider.resources.service_instance_resource.AaiService.get_all") diff --git a/tox.ini b/tox.ini index 5852af1..1aa0572 100644 --- a/tox.ini +++ b/tox.ini @@ -60,3 +60,10 @@ deps = types-PyYAML -rrequirements.txt commands = mypy --strict onap_data_provider/ + +[testenv:cov] +deps = + pytest-cov + -rrequirements.txt +commands = + pytest --cov-report term-missing --cov-report xml --cov-report html --cov=onap_data_provider --cov-fail-under=80 -- cgit 1.2.3-korg