From 2af8eed99a00371db238c1021fbe110df59fd476 Mon Sep 17 00:00:00 2001 From: paweldenst Date: Mon, 19 Dec 2022 08:38:11 +0000 Subject: Create CPS anchor nodes using ODP Added required anchor-name and dataspace-name for schema Issue-ID: INT-2179 Signed-off-by: paweldenst Change-Id: I98d3b25a724af16adf4943bcd832054ed43c69f0 --- onap_data_provider/resources/cps_resource.py | 48 ++++++++++++++++++++++-- onap_data_provider/resources/resource_creator.py | 12 ++++-- onap_data_provider/schemas/infra_1_1.schema | 20 ++++++++++ onap_data_provider/schemas/infra_2_0.schema | 20 ++++++++++ requirements.txt | 2 +- samples/cps.yaml | 5 +++ setup.py | 4 +- tests/test_cps_resource.py | 21 ++++++++--- 8 files changed, 117 insertions(+), 15 deletions(-) diff --git a/onap_data_provider/resources/cps_resource.py b/onap_data_provider/resources/cps_resource.py index c8e666f..cf1357a 100644 --- a/onap_data_provider/resources/cps_resource.py +++ b/onap_data_provider/resources/cps_resource.py @@ -14,17 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. """ - import logging from abc import ABC -from typing import Any, Dict +from typing import Any, Dict, Optional from onapsdk.cps import Anchor, Dataspace, SchemaSet # type: ignore from onapsdk.exceptions import APIError, ResourceNotFound # type: ignore - +from yaml import Node from onap_data_provider.resources.resource import Resource + class DataspaceSubresource(Resource, ABC): """Abstract dataspace subresource class.""" @@ -186,3 +186,45 @@ class DataspaceResource(Resource): anchor_data["anchor-name"]) else: logging.warning("Anchor %s already exists", anchor_data["anchor-name"]) + +class AnchorNodeResource(DataspaceSubresource): + """Anchor node resource class + + Creates CPS anchor node + """ + + def __init__(self, data: Dict[str, Any]) -> None: + """Initialize anchor resource""" + super().__init__(data) + + self._anchor: Anchor = None + def create(self) -> None: + """Create anchor node. + + Raises: + ValueError: Anchor doesn't exist + + """ + if not self.anchor: + raise ValueError("Anchor %s does not exist, create it first", self.data["anchor-name"]) + self.anchor.create_node(self.data.get("node-data")) + + @property + def anchor(self) -> Anchor: + """Anchor property. + + Tries to get anchor from dataspace. + + Returns: + Anchor: Anchor object, if anchor already exists. None otherwise. + + """ + if not self._anchor: + try: + self._anchor = self.dataspace.get_anchor(self.data["anchor-name"]) + except APIError as api_error: + if "Anchor not found" in str(api_error): + return None + else: + raise + return self._anchor diff --git a/onap_data_provider/resources/resource_creator.py b/onap_data_provider/resources/resource_creator.py index 35959f1..a8ccfbb 100644 --- a/onap_data_provider/resources/resource_creator.py +++ b/onap_data_provider/resources/resource_creator.py @@ -28,7 +28,7 @@ from .cloud_region_resource import CloudRegionResource from .complex_resource import ComplexResource from .customer_resource import CustomerResource from .data_dictionary_resource import DataDictionarySetResource -from .cps_resource import AnchorResource, DataspaceResource, SchemaSetResource +from .cps_resource import AnchorNodeResource, AnchorResource, DataspaceResource, SchemaSetResource from .line_of_business_resource import LineOfBusinessResource from .msb_k8s_definition import MsbK8SDefinitionResource from .owning_entity_resource import OwningEntityResource @@ -163,15 +163,19 @@ class ResourceCreator(ABC): }, "cps-dataspace": { VersionsEnum.V1_1: DataspaceResource, - VersionsEnum.V2_0: DataspaceResource + VersionsEnum.V2_0: DataspaceResource, }, "cps-schema-set": { VersionsEnum.V1_1: SchemaSetResource, - VersionsEnum.V2_0: SchemaSetResource + VersionsEnum.V2_0: SchemaSetResource, }, "cps-anchor": { VersionsEnum.V1_1: AnchorResource, - VersionsEnum.V2_0: AnchorResource + VersionsEnum.V2_0: AnchorResource, + }, + "cps-anchor-node": { + VersionsEnum.V1_1: AnchorNodeResource, + VersionsEnum.V2_0: AnchorNodeResource } } diff --git a/onap_data_provider/schemas/infra_1_1.schema b/onap_data_provider/schemas/infra_1_1.schema index d2480c6..e521f8e 100644 --- a/onap_data_provider/schemas/infra_1_1.schema +++ b/onap_data_provider/schemas/infra_1_1.schema @@ -755,3 +755,23 @@ properties: - schema-set-name required: - cps-anchor + cps-anchor-nodes: + type: array + items: + - type: object + properties: + cps-anchor-node: + type: object + properties: + anchor-name: + type: string + dataspace-name: + type: string + node-data: + type: string + required: + - node-data + - anchor-name + - dataspace-name + required: + - cps-anchor-node \ No newline at end of file diff --git a/onap_data_provider/schemas/infra_2_0.schema b/onap_data_provider/schemas/infra_2_0.schema index 59c6298..7ca55df 100644 --- a/onap_data_provider/schemas/infra_2_0.schema +++ b/onap_data_provider/schemas/infra_2_0.schema @@ -755,3 +755,23 @@ properties: - schema-set-name required: - cps-anchor + cps-anchor-nodes: + type: array + items: + - type: object + properties: + cps-anchor-node: + type: object + properties: + anchor-name: + type: string + dataspace-name: + type: string + node-data: + type: string + required: + - node-data + - anchor-name + - dataspace-name + required: + - cps-anchor-node \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index b06f7c5..193720d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -onapsdk==10.1.0 +onapsdk==10.3.2 PyYAML~=5.4.1 jsonschema==4.4.0 diff --git a/samples/cps.yaml b/samples/cps.yaml index 4c06fa6..68a612d 100644 --- a/samples/cps.yaml +++ b/samples/cps.yaml @@ -20,3 +20,8 @@ resources: anchor-name: test-odp-anchor schema-set-name: test-odp-schemaset dataspace-name: test-odp-dataspace + cps-anchor-nodes: + - cps-anchor-node: + anchor-name: test-odp-anchor + dataspace-name: test-odp-dataspace + node-data: '{"shops": {"bookstore": {"bookstore-name": "Chapters", "categories": [{"code": 1, "name": "SciFi", "books": {"book": [{"title": "2001: A Space Odyssey", "price": 5}, {"title": "Dune", "price": 5}]}}, {"code": 2, "name": "Kids", "books": {"book": [{"title": "Matilda"}]}}]}}}' diff --git a/setup.py b/setup.py index e9b1652..e37e916 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ with open("README.md", "r", encoding="utf-8") as readme: setuptools.setup( name="onap_data_provider", version="0.7.1", - author="Michal Jagiello , Piotr Stanior ", + author="Michal Jagiello , Piotr Stanior , Pawel Denst ", description="Tool to provide data for ONAP instances", long_description=long_description, long_description_content_type="text/markdown", @@ -35,7 +35,7 @@ setuptools.setup( "onap-data-provider=onap_data_provider.data_provider:run", ] }, - install_requires=["onapsdk==10.1.0", "PyYAML~=5.4.1", "jsonschema==4.4.0"], + install_requires=["onapsdk==10.3.2", "PyYAML~=5.4.1", "jsonschema==4.4.0"], classifiers=[ "Development Status :: 5 - Production/Stable", "Programming Language :: Python", diff --git a/tests/test_cps_resource.py b/tests/test_cps_resource.py index 2e01ad6..365f5c2 100644 --- a/tests/test_cps_resource.py +++ b/tests/test_cps_resource.py @@ -14,11 +14,9 @@ limitations under the License. """ from unittest.mock import MagicMock, NonCallableMagicMock, patch, PropertyMock - from onapsdk.exceptions import APIError, ResourceNotFound from pytest import raises - -from onap_data_provider.resources.cps_resource import AnchorResource, DataspaceResource, SchemaSetResource +from onap_data_provider.resources.cps_resource import AnchorNodeResource, AnchorResource, DataspaceResource, SchemaSetResource DATASPACE_RESOURCE_DATA = { @@ -40,7 +38,8 @@ DATASPACE_WITH_ANCHORS_DATA = { "anchors": [ { "anchor-name": "test-anchor", - "schema-set-name": "test-schema-set" + "schema-set-name": "test-schema-set", + "anchor-node-name": "test-anchor-node" } ] } @@ -54,7 +53,8 @@ SCHEMA_SET_DATA = { ANCHOR_DATA = { "anchor-name": "test-anchor", "dataspace-name": "test-dataspace", - "schema-set-name": "test-schema-set" + "schema-set-name": "test-schema-set", + "anchor-node-name": "test-anchor-node" } @@ -162,3 +162,14 @@ def test_anchor_resource(mock_dataspace_property, mock_schema_set_property): ar.create() mock_dataspace_property.return_value.get_anchor.assert_called_once_with("test-anchor") mock_dataspace_property.return_value.create_anchor.assert_not_called() + +@patch("onap_data_provider.resources.cps_resource.AnchorResource.schema_set", new_callable=PropertyMock) +@patch("onap_data_provider.resources.cps_resource.AnchorNodeResource.dataspace", new_callable=PropertyMock) +def test_anchor_node_resource(mock_dataspace_property, mock_schema_set_property): + ar = AnchorNodeResource(ANCHOR_DATA) + + mock_schema_set_property.side_effect = None + mock_schema_set_property.return_value = MagicMock() + ar.create() + mock_dataspace_property.return_value.create_node.assert_not_called() + mock_dataspace_property.return_value.get_anchor.assert_called_once_with("test-anchor") \ No newline at end of file -- cgit 1.2.3-korg