aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Jagiello <michal.jagiello@t-mobile.pl>2022-02-09 12:30:27 +0000
committerMichal Jagiello <michal.jagiello@t-mobile.pl>2022-02-14 11:44:09 +0000
commita8e2a839a4cb65e341c610fd2bd2e8968c754b3d (patch)
tree766c9b0c52c0e392f2ab79d87498623d1c016b77
parent0384b57fa175d45f5c3947adb488ef572669bce1 (diff)
Custom YAML tag to get already existed ONAP resources properties
Would be useful for Alloted Resources Issue-ID: INT-2075 Signed-off-by: Michal Jagiello <michal.jagiello@t-mobile.pl> Change-Id: Iad398a2f0c049ba73fa4569a0f2caed1311f077c
-rw-r--r--docs/source/index.rst1
-rw-r--r--docs/source/tags.rst33
-rw-r--r--onap_data_provider/config_loader.py3
-rw-r--r--onap_data_provider/property_tag/__init__.py21
-rw-r--r--onap_data_provider/property_tag/base.py73
-rw-r--r--onap_data_provider/property_tag/properties_getter.py64
-rw-r--r--onap_data_provider/property_tag/sdc_service.py52
-rw-r--r--onap_data_provider/tag_handlers.py22
-rw-r--r--tests/test_tag_handlers.py16
9 files changed, 283 insertions, 2 deletions
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 5cadde1..9360ed3 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -12,6 +12,7 @@ Welcome to ONAP data provider's documentation!
description
schemas
+ tags
usage
diff --git a/docs/source/tags.rst b/docs/source/tags.rst
new file mode 100644
index 0000000..b16e83e
--- /dev/null
+++ b/docs/source/tags.rst
@@ -0,0 +1,33 @@
+ONAP data provider custom YAML tags
+===================================
+
+In ONAP data provider we created a few custom YAML tags which could be used (and useful) in entities files.
+
+!join tag
+---------
+
+Concatenate multiple strings in YAML value.
+
+`!join [a, b, c]` result is `abc`
+
+`!join ['_', [a, b, c]]` result is `a_b_c`
+
+!uuid4 tag
+----------
+
+Generates a random UUID4
+
+`!uuid4` result is random UUID4 value
+
+!onap_resource_property
+-----------------------
+
+Gets the property value from the already existing ONAP resources.
+
+Available resources:
+
+* SDC service
+
+`!onap_resource_property service identifier service-model-name` result is a SDC service "service-model-name" model "identifier" property value
+
+`!onap_resource_property service identifier service-model-name 1.0` result is a SDC service "service-model-name" version 1.0 model "identifier" property value
diff --git a/onap_data_provider/config_loader.py b/onap_data_provider/config_loader.py
index 5757e1e..4507a14 100644
--- a/onap_data_provider/config_loader.py
+++ b/onap_data_provider/config_loader.py
@@ -17,11 +17,12 @@
from pathlib import Path
from typing import Any, Iterator, List
import yaml
-from onap_data_provider.tag_handlers import join, generate_random_uuid
+from onap_data_provider.tag_handlers import join, generate_random_uuid, resource_property
# register custom tag handlers in yaml.SafeLoader
yaml.add_constructor("!join", join, yaml.SafeLoader)
yaml.add_constructor("!uuid4", generate_random_uuid, yaml.SafeLoader)
+yaml.add_constructor("!onap_resource_property", resource_property, yaml.SafeLoader)
class ConfigLoader:
diff --git a/onap_data_provider/property_tag/__init__.py b/onap_data_provider/property_tag/__init__.py
new file mode 100644
index 0000000..1e88be1
--- /dev/null
+++ b/onap_data_provider/property_tag/__init__.py
@@ -0,0 +1,21 @@
+"""Resource property tag package.
+
+There the package modules are going to be implemented.
+Each module represents one resource which can be used with "!onap_resource_property" tag.
+
+"""
+"""
+ Copyright 2022 Deutsche Telekom AG
+
+ 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.
+""" \ No newline at end of file
diff --git a/onap_data_provider/property_tag/base.py b/onap_data_provider/property_tag/base.py
new file mode 100644
index 0000000..7ae7102
--- /dev/null
+++ b/onap_data_provider/property_tag/base.py
@@ -0,0 +1,73 @@
+"""Base module for property tag classes."""
+"""
+ Copyright 2022 Deutsche Telekom AG
+
+ 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 abc import ABC
+from typing import Any, Type
+
+from onapsdk.onap_service import OnapService # type: ignore
+
+
+class BasePropertyTagResource(ABC):
+ """Base property tag resource class.
+
+ Abstract class which all resource classes should inherit from.
+ Subclasses has to implement `resource` property to get the valid object
+ using Python ONAP SDK classes.
+
+ Subclass could also implement `__init__` method to get more attributes from
+ the user which uses the tag.
+
+ """
+
+ def __init__(self, property_name: str) -> None:
+ """Init property tag resource object.
+
+ Args:
+ property_name (str): Name of the property to get
+
+ """
+ self.property_name: str = property_name
+
+ @property
+ def resource(self) -> OnapService:
+ """Resource property abstract method.
+
+ Returns an object from which the property is going to be get.
+
+ Raises:
+ NotImplementedError: That method is an abstract one
+
+ Returns:
+ OnapService: Any OnapService subclass
+
+ """
+ raise NotImplementedError
+
+ @property
+ def resource_property(self) -> Any:
+ """Resource property.
+
+ Using `getattr` function get the property from resource.
+
+ Returns:
+ Any: Property value
+
+ Raises:
+ AttributeError: Resource has no property with given name.
+
+ """
+ return getattr(self.resource, self.property_name)
diff --git a/onap_data_provider/property_tag/properties_getter.py b/onap_data_provider/property_tag/properties_getter.py
new file mode 100644
index 0000000..df29314
--- /dev/null
+++ b/onap_data_provider/property_tag/properties_getter.py
@@ -0,0 +1,64 @@
+"""Properties getter module."""
+"""
+ Copyright 2022 Deutsche Telekom AG
+
+ 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 logging
+from typing import Any, Mapping, Type, TYPE_CHECKING
+
+from .base import BasePropertyTagResource
+from .sdc_service import SdcServicePropertyTagResource
+
+if TYPE_CHECKING:
+ from typing import Any, Mapping
+
+
+class PropertiesGetter:
+ """Properties getter class.
+
+ Uses to get values of properties from already existing ONAP resources.
+
+ Contains a mapper to select right class to get the values from.
+ """
+
+ RESOURCES: Mapping[str, Type[BasePropertyTagResource]] = {
+ "service": SdcServicePropertyTagResource
+ }
+
+ @classmethod
+ def get_property(cls, resource_type: str, *args: str) -> Any:
+ """Get property class method.
+
+ Maps the input `resource_type` into `BasePropertyTagResource` class
+ and get it's `resource_property` property
+
+ Args:
+ resource_type (str): Type of the resource - uses by a mapper
+ *args (str): Args to be passed to the service class init
+
+ Raises:
+ ValueError: Given resource type is not supported
+
+ Returns:
+ Any: Resource property value
+
+ """
+ try:
+ return cls.RESOURCES[resource_type](*args).resource_property
+ except KeyError:
+ msg = f"Resource type \"{resource_type}\" is not supported"
+ logging.error(msg)
+ raise ValueError(msg)
+
diff --git a/onap_data_provider/property_tag/sdc_service.py b/onap_data_provider/property_tag/sdc_service.py
new file mode 100644
index 0000000..b8eca80
--- /dev/null
+++ b/onap_data_provider/property_tag/sdc_service.py
@@ -0,0 +1,52 @@
+"""SDC property module used by tag to get resource's property"""
+"""
+ Copyright 2022 Deutsche Telekom AG
+
+ 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 typing import Optional
+
+from onapsdk.onap_service import OnapService # type: ignore
+from onapsdk.sdc.service import Service # type: ignore
+
+from .base import BasePropertyTagResource
+
+
+class SdcServicePropertyTagResource(BasePropertyTagResource):
+ """Class to get property from SDC service module objects."""
+
+ def __init__(self, property_name: str, service_name: str, version: Optional[str] = None) -> None:
+ """Initialize object.
+
+ Get the name of the property to get, serivce name and optional version of the service.
+
+ Args:
+ property_name (str): Property name
+ service_name (str): Service name
+ version (Optional[str], optional): Optional version. If no version is given
+ the latest version of the service will be loaded. Defaults to None.
+ """
+ super().__init__(property_name)
+ self.service_name: str = service_name
+ self.version: Optional[str] = version
+
+ @property
+ def resource(self) -> Service:
+ """Service resource.
+
+ Returns:
+ Service: Service with the provided name and version.
+
+ """
+ return Service(self.service_name, version=self.version)
diff --git a/onap_data_provider/tag_handlers.py b/onap_data_provider/tag_handlers.py
index 1f8a21a..d8c9738 100644
--- a/onap_data_provider/tag_handlers.py
+++ b/onap_data_provider/tag_handlers.py
@@ -19,6 +19,8 @@ from typing import Any
import yaml
+from .property_tag.properties_getter import PropertiesGetter
+
def join(loader: yaml.SafeLoader, node: yaml.Node) -> str:
"""Concatinates the nodes fields for !join tag.
@@ -52,3 +54,23 @@ def generate_random_uuid(*_: Any) -> str:
str: randomly generated UUID
"""
return str(uuid.uuid4())
+
+
+def resource_property(loader: yaml.SafeLoader, node: yaml.Node) -> Any:
+ """Resource property tag method.
+
+ Constructs a scalar from the YAML node and uses `PropertiesGetter`
+ to get a property value from already existing ONAP resource.
+
+ Args:
+ loader (yaml.SafeLoader): YAML Safe Loader
+ node (yaml.Node): Node to get values from
+
+ Raises:
+ ValueError: Given property type from the node is not supported by a tag
+
+ Returns:
+ Any: Resource's property value
+ """
+ resource_type, *args = loader.construct_scalar(node).split(" ") # type: ignore
+ return PropertiesGetter.get_property(resource_type, *args)
diff --git a/tests/test_tag_handlers.py b/tests/test_tag_handlers.py
index 719295f..c7c9ffc 100644
--- a/tests/test_tag_handlers.py
+++ b/tests/test_tag_handlers.py
@@ -1,5 +1,8 @@
from unittest.mock import patch, PropertyMock
-from onap_data_provider.tag_handlers import join, generate_random_uuid
+
+import pytest
+
+from onap_data_provider.tag_handlers import join, generate_random_uuid, resource_property
def test_generate_random_uuid():
@@ -13,3 +16,14 @@ def test_generate_random_uuid():
def test_join(mock_safe_loader):
mock_safe_loader.construct_sequence.return_value = ["-", ["cloud", "owner", "DC1"]]
assert join(mock_safe_loader, None) == "cloud-owner-DC1"
+
+
+@patch("yaml.SafeLoader", new_callable=PropertyMock)
+@patch("onap_data_provider.property_tag.sdc_service.Service")
+def test_resource_property(mock_service, mock_safe_loader):
+ mock_safe_loader.construct_scalar.return_value = "unknown"
+ with pytest.raises(ValueError, match="Resource type \"unknown\" is not supported"):
+ resource_property(mock_safe_loader, None)
+ mock_service.return_value.identifier = "123"
+ mock_safe_loader.construct_scalar.return_value = "service identifier test_name"
+ assert resource_property(mock_safe_loader, None) == "123"