aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/source/schemas/resources/shared/xnf_resources.rst18
-rw-r--r--docs/source/schemas/version_1_0.rst32
-rw-r--r--docs/source/schemas/version_1_1.rst36
-rw-r--r--onap_data_provider/resources/data_dictionary_resource.py66
-rw-r--r--onap_data_provider/resources/resource_creator.py7
-rw-r--r--onap_data_provider/resources/sdc_properties_mixins.py53
-rw-r--r--onap_data_provider/resources/xnf_resource.py12
-rw-r--r--onap_data_provider/schemas/infra.schema38
-rw-r--r--onap_data_provider/schemas/infra_1_1.schema40
-rw-r--r--samples/service.yaml54
-rw-r--r--samples/xnfs.yaml6
-rw-r--r--tests/test_data_dictionary_resource.py34
-rw-r--r--tests/test_pnf_resource.py36
-rw-r--r--tests/test_vnf_resource.py36
14 files changed, 442 insertions, 26 deletions
diff --git a/docs/source/schemas/resources/shared/xnf_resources.rst b/docs/source/schemas/resources/shared/xnf_resources.rst
new file mode 100644
index 0000000..71ad609
--- /dev/null
+++ b/docs/source/schemas/resources/shared/xnf_resources.rst
@@ -0,0 +1,18 @@
+Resources
+^^^^^^^^^
+
+.. list-table::
+ :header-rows: 1
+
+ * - Property
+ - Type
+ - Required
+ - Comment
+ * - name
+ - string
+ - YES
+ -
+ * - xnf_type
+ - string
+ - YES
+ - \ No newline at end of file
diff --git a/docs/source/schemas/version_1_0.rst b/docs/source/schemas/version_1_0.rst
index ffc65ca..a7f700a 100644
--- a/docs/source/schemas/version_1_0.rst
+++ b/docs/source/schemas/version_1_0.rst
@@ -196,6 +196,10 @@ PNF
- List of `PNF Properties 1.0`_
- NO
-
+ * - resources
+ - List of `PNF Resources 1.0`_
+ - NO
+ -
.. _PNF deployment artifact 1.0:
@@ -205,6 +209,10 @@ PNF
.. include:: /schemas/resources/shared/xnf_property.rst
+.. _PNF resources 1.0:
+
+.. include:: /schemas/resources/shared/xnf_resources.rst
+
VNF
---
@@ -231,6 +239,10 @@ VNF
- List of `VNF properties 1.0`_
- NO
-
+ * - resources
+ - List of `VNF Resources 1.0`_
+ - NO
+ -
.. _VNF deployment artifact 1.0:
@@ -248,6 +260,11 @@ VNF
.. include:: /schemas/resources/shared/line_of_business.rst
+.. _VNF resources 1.0:
+
+.. include:: /schemas/resources/shared/xnf_resources.rst
+
+
MSB k8s definition
------------------
@@ -399,3 +416,18 @@ VF modules instantiation parameters
- List of key-value parameters
- NO
-
+
+Data dictionary
+---------------
+
+.. list-table::
+ :header-rows: 1
+
+ * - Property
+ - Type
+ - Required
+ - Comment
+ * - file-path
+ - string
+ - YES
+ -
diff --git a/docs/source/schemas/version_1_1.rst b/docs/source/schemas/version_1_1.rst
index 152e018..ce74c91 100644
--- a/docs/source/schemas/version_1_1.rst
+++ b/docs/source/schemas/version_1_1.rst
@@ -200,6 +200,10 @@ Service inputs
- boolean
- NO
- Determines if nested input is going to be created
+ * - resource-property
+ - boolean
+ - NO
+ - Determines whether use resource's property as an input
* - resource
- boolean
- NO
@@ -243,6 +247,10 @@ PNF
- List of `PNF Properties 1.1`_
- NO
-
+ * - resources
+ - List of `PNF Resources 1.1`_
+ - NO
+ -
.. _PNF deployment artifact 1.1:
@@ -252,6 +260,10 @@ PNF
.. include:: /schemas/resources/shared/xnf_property.rst
+.. _PNF resources 1.1:
+
+.. include:: /schemas/resources/shared/xnf_resources.rst
+
VNF
---
@@ -290,6 +302,10 @@ VNF
- List of `VNF properties 1.1`_
- NO
-
+ * - resources
+ - List of `VNF Resources 1.1`_
+ - NO
+ -
.. _VNF deployment artifact 1.1:
@@ -299,6 +315,11 @@ VNF
.. include:: /schemas/resources/shared/owning_entity.rst
+.. _VNF resources 1.1:
+
+.. include:: /schemas/resources/shared/xnf_resources.rst
+
+
MSB k8s definition
------------------
@@ -450,3 +471,18 @@ VF modules instantiation parameters
- List of key-value parameters
- NO
-
+
+Data dictionary
+---------------
+
+.. list-table::
+ :header-rows: 1
+
+ * - Property
+ - Type
+ - Required
+ - Comment
+ * - file-path
+ - string
+ - YES
+ -
diff --git a/onap_data_provider/resources/data_dictionary_resource.py b/onap_data_provider/resources/data_dictionary_resource.py
new file mode 100644
index 0000000..4c9402e
--- /dev/null
+++ b/onap_data_provider/resources/data_dictionary_resource.py
@@ -0,0 +1,66 @@
+"""Customer resource 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, Dict
+from onapsdk.cds import DataDictionarySet # type: ignore
+
+from onapsdk.exceptions import FileError # type: ignore
+from onap_data_provider.resources.resource import Resource
+
+
+class DataDictionarySetResource(Resource):
+ """DataDictionarySet resource class
+
+ creates Data Dictionaries
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ """Initialize data dictionary set resource
+
+ Args:
+ data (Dict[str, Any]): Data needed to create resource.
+ """
+ super().__init__(data)
+ self._data_dictionaries: DataDictionarySet = None
+
+ def create(self) -> None:
+ """Create data dictionaries.
+
+ Create data dictionaries from input data.
+ """
+ if self.data_dictionaries:
+ self.data_dictionaries.upload()
+
+ @property
+ def data_dictionaries(self) -> DataDictionarySet:
+ """Get DataDictionarySet.
+
+ Returns:
+ DataDictionarySet: Created DataDictionarySet containing DataDictionary instances.
+ """
+ if not self._data_dictionaries:
+ try:
+ self._data_dictionaries = DataDictionarySet.load_from_file(
+ self.data.get("file-path")
+ )
+ except FileError:
+ logging.error(
+ f"Error when reading from file {self.data.get('file-path')}"
+ )
+ return None
+ return self._data_dictionaries
diff --git a/onap_data_provider/resources/resource_creator.py b/onap_data_provider/resources/resource_creator.py
index 34cbafd..de9ee9b 100644
--- a/onap_data_provider/resources/resource_creator.py
+++ b/onap_data_provider/resources/resource_creator.py
@@ -38,6 +38,7 @@ from .service_instance_resource import (
from .vendor_resource import VendorResource
from .vnf_resource import VnfResource
from .vsp_resource import VspResource
+from .data_dictionary_resource import DataDictionarySetResource
from ..versions import VersionsEnum
if typing.TYPE_CHECKING:
@@ -128,6 +129,11 @@ class ResourceCreator(ABC):
VersionsEnum.V1_0: MsbK8SDefinitionResource,
VersionsEnum.V1_1: MsbK8SDefinitionResource,
},
+ "data-dictionaries": {
+ VersionsEnum.NONE: DataDictionarySetResource,
+ VersionsEnum.V1_0: DataDictionarySetResource,
+ VersionsEnum.V1_1: DataDictionarySetResource,
+ },
}
@classmethod
@@ -157,6 +163,7 @@ class ResourceCreator(ABC):
- platform: PlatformResource
- owning-entity: OwningEntityResource
- msb-k8s-definition: MsbK8SDefinitionResource
+ - data-dictionaries: DataDictionarySetResource
Args:
resource_type (str): Resource type to create
diff --git a/onap_data_provider/resources/sdc_properties_mixins.py b/onap_data_provider/resources/sdc_properties_mixins.py
index 28d06c3..1b93365 100644
--- a/onap_data_provider/resources/sdc_properties_mixins.py
+++ b/onap_data_provider/resources/sdc_properties_mixins.py
@@ -20,8 +20,9 @@ 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 NestedInput, Property # type: ignore
+from onapsdk.sdc.properties import NestedInput, Property, ComponentProperty # type: ignore
from onapsdk.sdc.sdc_resource import SdcResource # type: ignore
+from onapsdk.sdc.vf import Vf # type: ignore
class SdcPropertiesMixins(ABC):
@@ -116,24 +117,50 @@ class SdcPropertiesMixins(ABC):
comp: Component = propresource.get_component_by_name(data["resource"])
propresource.declare_input(NestedInput(comp.sdc_resource, comp.sdc_resource.get_input(data["name"])))
+ def declare_resource_property_input(
+ self, sdc_resource: Union[SdcResource, Component], input_data: Dict[str, Any]
+ ) -> None:
+ """Declare input from resource's property.
+
+ Args:
+ sdc_resource (SdcResource): Resource for which input is going to be declared
+ input_data (Dict[str, Any]): Data used for input creation.
+ """
+ if not isinstance(sdc_resource, Vf):
+ logging.error("Resource property as input is currently supported only for Vf resources.")
+ return
+ resource_component: Component = sdc_resource.get_component_by_name(
+ input_data["resource"]
+ )
+ component_property: ComponentProperty = resource_component.get_property(
+ input_data["name"]
+ )
+ sdc_resource.declare_input(component_property)
+
def set_inputs(
- self, propresource: Union[SdcResource, Component], data: List[Dict[str, Any]]
+ self, sdc_resource: Union[SdcResource, Component], inputs_data: List[Dict[str, Any]],
) -> None:
- """Set inputs of an SdcResource.
+ """Set inputs of an SdcResource.
Args:
- sdcresource (SdcResource): the SdcResource the inputs should belong to
- data (Dict[str, Any]): Data needed to create resource.
+ sdc_resource (SdcResource): the SdcResource the inputs should belong to
+ inputs_data (Dict[str, Any]): Input data to be set into resource.
"""
- for property_data in data: # type: Dict[str, Any]
- if property_data.get("nested-input"):
- self.declare_nested_input(propresource, property_data)
+ for input_data in inputs_data: # type: Dict[str, Any]
+ if input_data.get("nested-input"):
+ self.declare_nested_input(sdc_resource, input_data)
+ elif input_data.get("resource-property"):
+ self.declare_resource_property_input(sdc_resource, input_data)
+ # In case resource already has input with given name then set its value only
elif any(
- (prop.name == property_data["name"] for prop in propresource.inputs)
+ (
+ resource_input.name == input_data["name"]
+ for resource_input in sdc_resource.inputs
+ )
):
- propresource.set_input_default_value(
- propresource.get_input(property_data["name"]),
- property_data.get("value"),
+ sdc_resource.set_input_default_value(
+ sdc_resource.get_input(input_data["name"]),
+ input_data.get("value"),
)
else:
- self.declare_input(propresource, property_data)
+ self.declare_input(sdc_resource, input_data)
diff --git a/onap_data_provider/resources/xnf_resource.py b/onap_data_provider/resources/xnf_resource.py
index 63b01dc..29b5011 100644
--- a/onap_data_provider/resources/xnf_resource.py
+++ b/onap_data_provider/resources/xnf_resource.py
@@ -16,10 +16,12 @@
"""
from abc import ABC
+import logging
from typing import Any, Dict
from onapsdk.sdc.vsp import Vsp # type: ignore
from onapsdk.sdc.sdc_resource import SdcResource # type: ignore
from onapsdk.sdc.properties import Property # type: ignore
+from onapsdk.sdc.vfc import Vfc # type: ignore
from .sdc_properties_mixins import SdcPropertiesMixins
@@ -44,13 +46,21 @@ class XnfResource(SdcPropertiesMixins, ABC):
if (vsp_name := data.get("vsp")) is not None:
self._xnf.vsp = Vsp(vsp_name)
self._xnf.create()
- if (artifact_data := data.get("deployment_artifact")) is not None:
+ if data.get("deployment_artifact") is not None:
self._xnf.add_deployment_artifact(
artifact_type=data["deployment_artifact"]["artifact_type"],
artifact_name=data["deployment_artifact"]["artifact_name"],
artifact_label=data["deployment_artifact"]["artifact_label"],
artifact=data["deployment_artifact"]["artifact_file_name"],
)
+ if (resources := data.get("resources")) is not None:
+ for resource_data in resources:
+ if resource_data["xnf_type"] == "VFC":
+ self._xnf.add_resource(Vfc(name=resource_data["name"]))
+ else:
+ logging.warning(
+ f"Provided xNF resource of type {resource_data['xnf_type']} is not supported."
+ )
self.set_properties(self._xnf, data.get("properties", []))
self.set_inputs(self._xnf, data.get("inputs", []))
self._xnf.onboard()
diff --git a/onap_data_provider/schemas/infra.schema b/onap_data_provider/schemas/infra.schema
index 55c5cbf..d276755 100644
--- a/onap_data_provider/schemas/infra.schema
+++ b/onap_data_provider/schemas/infra.schema
@@ -318,6 +318,18 @@ properties:
- artifact_file_name
properties: *props
inputs: *props
+ resources:
+ type: array
+ items:
+ - type: object
+ properties:
+ xnf_type:
+ type: string
+ name:
+ type: string
+ required:
+ - xnf_type
+ - name
required:
- name
required:
@@ -352,6 +364,18 @@ properties:
- artifact_file_name
properties: *props
inputs: *props
+ resources:
+ type: array
+ items:
+ - type: object
+ properties:
+ xnf_type:
+ type: string
+ name:
+ type: string
+ required:
+ - xnf_type
+ - name
required:
- name
required:
@@ -525,3 +549,17 @@ properties:
- name
- version
- artifact
+ data-dictionaries-sets:
+ type: array
+ items:
+ - type: object
+ properties:
+ data-dictionaries:
+ type: object
+ properities:
+ file-path:
+ type: string
+ required:
+ - file-path
+ required:
+ - data-dictionaries
diff --git a/onap_data_provider/schemas/infra_1_1.schema b/onap_data_provider/schemas/infra_1_1.schema
index 063e78a..8320b74 100644
--- a/onap_data_provider/schemas/infra_1_1.schema
+++ b/onap_data_provider/schemas/infra_1_1.schema
@@ -292,6 +292,8 @@ properties:
type: string
nested-input:
type: boolean
+ resource-property:
+ type: boolean
resource:
type: string
value:
@@ -352,6 +354,18 @@ properties:
- artifact_file_name
properties: *props
inputs: *props
+ resources:
+ type: array
+ items:
+ - type: object
+ properties:
+ xnf_type:
+ type: string
+ name:
+ type: string
+ required:
+ - xnf_type
+ - name
required:
- name
required:
@@ -392,6 +406,18 @@ properties:
- artifact_file_name
properties: *props
inputs: *props
+ resources:
+ type: array
+ items:
+ - type: object
+ properties:
+ xnf_type:
+ type: string
+ name:
+ type: string
+ required:
+ - xnf_type
+ - name
required:
- name
required:
@@ -567,3 +593,17 @@ properties:
- name
- version
- artifact
+ data-dictionaries-sets:
+ type: array
+ items:
+ - type: object
+ properties:
+ data-dictionaries:
+ type: object
+ properities:
+ file-path:
+ type: string
+ required:
+ - file-path
+ required:
+ - data-dictionaries
diff --git a/samples/service.yaml b/samples/service.yaml
index 36c92d7..8472f1b 100644
--- a/samples/service.yaml
+++ b/samples/service.yaml
@@ -24,11 +24,21 @@ resources:
- name: sample-vnf # Make sure it exists!
type: VF
properties:
- controller_actor: "CDS"
- skip_post_instantiation_configuration: False
- sdnc_artifact_name: "vnf"
- sdnc_model_version: "1.0.0"
- sdnc_model_name: "ubuntu20"
+ - name: controller_actor
+ type: string
+ value: "CDS"
+ - name: skip_post_instantiation_configuration
+ type: boolean
+ value: False
+ - name: sdnc_artifact_name
+ type: string
+ value: "vnf"
+ - name: sdnc_model_version
+ type: string
+ value: "1.0.0"
+ - name: sdnc_model_name
+ type: string
+ value: "ubuntu20"
- service:
name: sample-service-with-pnf
resources:
@@ -40,13 +50,37 @@ resources:
- name: sample-pnf # Make sure it exists!
type: PNF
properties:
- controller_actor: "CDS"
- skip_post_instantiation_configuration: False
- sdnc_artifact_name: "vnf"
- sdnc_model_version: "1.0.0"
- sdnc_model_name: "ubuntu20"
+ - name: controller_actor
+ type: string
+ value: "CDS"
+ - name: skip_post_instantiation_configuration
+ type: boolean
+ value: False
+ - name: sdnc_artifact_name
+ type: string
+ value: "vnf"
+ - name: sdnc_model_version
+ type: string
+ value: "1.0.0"
+ - name: sdnc_model_name
+ type: string
+ value: "ubuntu20"
- service:
name: sample-service-with-vl
resources:
- name: sample-vl # Make sure it exists!
type: VL
+
+ - service:
+ name: test-nested-inputs-service-1
+ category: Network L4+
+ description: LFN demo service
+ instantiation-type: Macro
+ resources:
+ - name: test-ar-pnf
+ type: PNF
+ inputs:
+ - resource-property: true
+ resource: test-ar-pnf
+ name: resource-property-name
+ value: test
diff --git a/samples/xnfs.yaml b/samples/xnfs.yaml
index 81f344b..805a2c1 100644
--- a/samples/xnfs.yaml
+++ b/samples/xnfs.yaml
@@ -25,6 +25,12 @@ resources:
vendor: sample-vendor # Make sure it exists!
category: Allotted Resource
subcategory: Allotted Resource
+ - vnf:
+ name: sample-vnf-with-vfc-as-property
+ vsp: sample-vsp # Make sure it exists!
+ resources:
+ - xnf_type: "VFC"
+ name: "AllottedResource"
pnfs:
- pnf:
diff --git a/tests/test_data_dictionary_resource.py b/tests/test_data_dictionary_resource.py
new file mode 100644
index 0000000..31369f7
--- /dev/null
+++ b/tests/test_data_dictionary_resource.py
@@ -0,0 +1,34 @@
+from unittest.mock import patch, PropertyMock
+
+from onapsdk.cds import DataDictionarySet
+from onapsdk.exceptions import FileError
+from onap_data_provider.resources.data_dictionary_resource import (
+ DataDictionarySetResource,
+)
+
+
+@patch(
+ "onap_data_provider.resources.data_dictionary_resource.DataDictionarySet.load_from_file"
+)
+def test_data_dictionary_resource_data_dictionary_set(
+ mock_data_dictionary_set_load_from_file,
+):
+ dds = DataDictionarySetResource({"json-file-path": "test"})
+ mock_data_dictionary_set_load_from_file.return_value = 1
+ assert dds.data_dictionaries is not None
+
+
+@patch("onap_data_provider.resources.data_dictionary_resource.DataDictionarySet.upload")
+@patch(
+ "onap_data_provider.resources.data_dictionary_resource.DataDictionarySet.load_from_file"
+)
+def test_data_dictionary_resource_data_dictionary_set_create(
+ mock_load_from_file, mock_data_dictionary_set_upload
+):
+ ddsr = DataDictionarySetResource({"file-path": "test"})
+ mock_load_from_file.side_effect = FileError
+ mock_data_dictionary_set_upload.assert_not_called()
+ mock_load_from_file.side_effect = None
+ mock_load_from_file.return_value = DataDictionarySet()
+ ddsr.create()
+ mock_data_dictionary_set_upload.assert_called()
diff --git a/tests/test_pnf_resource.py b/tests/test_pnf_resource.py
index c58717a..62dc3ae 100644
--- a/tests/test_pnf_resource.py
+++ b/tests/test_pnf_resource.py
@@ -1,4 +1,4 @@
-from unittest.mock import patch, PropertyMock
+from unittest.mock import MagicMock, patch, PropertyMock
from onap_data_provider.resources.pnf_resource import PnfResource
@@ -26,3 +26,37 @@ def test_pnf_resource_pnf(mock_pnf_created):
assert pnf_resource.pnf is None
mock_pnf_created.return_value = True
assert pnf_resource.pnf is not None
+
+
+@patch(
+ "onap_data_provider.resources.pnf_resource.Pnf.create",
+)
+@patch(
+ "onap_data_provider.resources.pnf_resource.Pnf.add_resource",
+)
+@patch(
+ "onap_data_provider.resources.pnf_resource.Pnf.onboard",
+)
+@patch(
+ "onap_data_provider.resources.pnf_resource.PnfResource.pnf",
+ new_callable=PropertyMock,
+)
+@patch(
+ "onap_data_provider.resources.xnf_resource.Vfc",
+)
+def test_pnf_resource_onboards_with_vfc(
+ mock_vfc, mock_pnf, mock_onboard, mock_add_resource, mock_pnf_create
+):
+ mock_vfc = MagicMock()
+ mock_pnf.return_value = None
+ data_no_composition = {"name": "test_pnf"}
+ pnf_resource = PnfResource(data_no_composition)
+ pnf_resource.create()
+ mock_add_resource.assert_not_called()
+ data_with_composition = {
+ "name": "test_pnf",
+ "resources": [{"name": "test", "xnf_type": "VFC"}],
+ }
+ pnf_resource = PnfResource(data_with_composition)
+ pnf_resource.create()
+ mock_add_resource.assert_called_once()
diff --git a/tests/test_vnf_resource.py b/tests/test_vnf_resource.py
index 6398aec..e35cded 100644
--- a/tests/test_vnf_resource.py
+++ b/tests/test_vnf_resource.py
@@ -1,4 +1,4 @@
-from unittest.mock import patch, PropertyMock
+from unittest.mock import MagicMock, patch, PropertyMock
from onap_data_provider.resources.vnf_resource import VnfResource
@@ -26,3 +26,37 @@ def test_vnf_resource_vnf(mock_vnf_created):
assert vnf_resource.vnf is None
mock_vnf_created.return_value = True
assert vnf_resource.vnf is not None
+
+
+@patch(
+ "onap_data_provider.resources.vnf_resource.Vf.create",
+)
+@patch(
+ "onap_data_provider.resources.vnf_resource.Vf.add_resource",
+)
+@patch(
+ "onap_data_provider.resources.vnf_resource.Vf.onboard",
+)
+@patch(
+ "onap_data_provider.resources.vnf_resource.VnfResource.vnf",
+ new_callable=PropertyMock,
+)
+@patch(
+ "onap_data_provider.resources.xnf_resource.Vfc",
+)
+def test_vnf_resource_onboards_with_vfc(
+ mock_vfc, mock_vnf, mock_onboard, mock_add_resource, mock_vnf_create
+):
+ mock_vfc = MagicMock()
+ mock_vnf.return_value = None
+ data_no_composition = {"name": "test_vnf"}
+ vnf_resource = VnfResource(data_no_composition)
+ vnf_resource.create()
+ mock_add_resource.assert_not_called()
+ data_with_composition = {
+ "name": "test_vnf",
+ "resources": [{"name": "test", "xnf_type": "VFC"}],
+ }
+ vnf_resource = VnfResource(data_with_composition)
+ vnf_resource.create()
+ mock_add_resource.assert_called_once()