From 04e8c7658c0ed31a334cf64fcfd4aa5f1962b39d Mon Sep 17 00:00:00 2001 From: Michal Jagiello Date: Mon, 27 Jun 2022 12:59:33 +0000 Subject: [Data provider] Add relationships between some A&AI resources Create relationship between: Tenant <-> Line of business Tenant <-> Owning entity Cloud region <-> Project Issue-ID: INT-2126 Signed-off-by: Michal Jagiello Change-Id: I3523c02b28b5fe972c0fbba112c8ffa532feadb8 --- Dockerfile | 4 +- .../resources/cloud_region_resource.py | 39 ++++--- onap_data_provider/resources/tenant_resource.py | 29 +++++ onap_data_provider/schemas/infra.schema | 14 +-- onap_data_provider/schemas/infra_1_1.schema | 121 +++++++++++---------- requirements.txt | 4 +- samples/cloud-region.yaml | 15 ++- setup.py | 3 +- tests/test_cloud_region_resource.py | 11 +- 9 files changed, 150 insertions(+), 90 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6f12536..fb07095 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9-slim AS builder +FROM python:3.10.4-slim AS builder COPY requirements.txt /opt/app/onap_data_provider/requirements.txt @@ -6,7 +6,7 @@ WORKDIR /opt/app/onap_data_provider/ RUN python -m pip install -r requirements.txt --prefix=/opt/install -FROM nexus3.onap.org:10001/onap/integration-python:9.1.0 +FROM nexus3.onap.org:10001/onap/integration-python:10.0.0 COPY --from=builder --chown=onap:onap /opt/install /usr/local diff --git a/onap_data_provider/resources/cloud_region_resource.py b/onap_data_provider/resources/cloud_region_resource.py index 7bcc3b4..9f66b48 100644 --- a/onap_data_provider/resources/cloud_region_resource.py +++ b/onap_data_provider/resources/cloud_region_resource.py @@ -21,6 +21,8 @@ from onap_data_provider.resources.esr_system_info_resource import ( import logging from typing import Any, Dict +from onapsdk.aai.aai_element import Relationship # type: ignore +from onapsdk.aai.business import Project # type: ignore from onapsdk.aai.cloud_infrastructure import CloudRegion, Complex # type: ignore from onapsdk.msb.k8s.connectivity_info import ConnectivityInfo # type: ignore from onapsdk.so.so_db_adapter import SoDbAdapter, IdentityService # type: ignore @@ -122,6 +124,20 @@ class CloudRegionResource(Resource): IdentityService("DEFAULT_KEYSTONE"), ) + # Link with project + for project_data in self.data.get("projects", []): + try: + project: Project = Project.get_by_name(project_data["project"]["name"]) + except ResourceNotFound: + project = Project.create(project_data["project"]["name"]) + project.add_relationship( + Relationship( + related_to="cloud-region", + related_link=self.cloud_region.url, + relationship_data=[] + ) + ) + @property def exists(self) -> bool: """Determine if resource already exists or not. @@ -156,21 +172,16 @@ class CloudRegionResource(Resource): return self._cloud_region def _link_to_complex(self, complex_physical_id: str) -> None: - try: # TODO: change it when https://gitlab.com/Orange-OpenSource/lfn/onap/python-onapsdk/-/issues/120 is fixed - if self.cloud_region.complex: - logging.info( - "Cloud region has relationship with complex: %s. New relationship can't be created", - self.cloud_region.complex.physical_location_id, - ) - return - except ResourceNotFound: - logging.debug("Cloud region has no complex linked with") - try: - complex: Complex = next( - Complex.get_all(physical_location_id=complex_physical_id) + if self.cloud_region.complex: + logging.info( + "Cloud region has relationship with complex: %s. New relationship can't be created", + self.cloud_region.complex.physical_location_id, ) - self.cloud_region.link_to_complex(complex) - except StopIteration: + return + try: + cmplx: Complex = Complex.get_by_physical_location_id(complex_physical_id) + self.cloud_region.link_to_complex(cmplx) + except ResourceNotFound: logging.error( "Complex %s does not exist, please create it before cloud region creation", complex_physical_id, diff --git a/onap_data_provider/resources/tenant_resource.py b/onap_data_provider/resources/tenant_resource.py index 13d003f..b4bca68 100644 --- a/onap_data_provider/resources/tenant_resource.py +++ b/onap_data_provider/resources/tenant_resource.py @@ -17,7 +17,9 @@ import logging from typing import Any, Dict, Optional +from onapsdk.aai.aai_element import Relationship # type: ignore from onapsdk.aai.cloud_infrastructure import CloudRegion, Tenant # type: ignore +from onapsdk.aai.business import LineOfBusiness, OwningEntity # type: ignore from .resource import Resource from onapsdk.exceptions import ResourceNotFound # type: ignore @@ -54,6 +56,33 @@ class TenantResource(Resource): tenant_context=self.data.get("tenant-context"), ) + for lines_of_business_data in self.data.get("lines-of-business", []): + try: + line_of_business: LineOfBusiness = LineOfBusiness.get_by_name(lines_of_business_data["line-of-business"]["name"]) + except ResourceNotFound: + line_of_business = LineOfBusiness.create(lines_of_business_data["line-of-business"]["name"]) + line_of_business.add_relationship( + Relationship( + related_to="tenant", + related_link=self.tenant.url, + relationship_data=[] + ) + ) + + for owning_entities_data in self.data.get("owning-entities", []): + try: + owning_entity: OwningEntity = OwningEntity.get_by_owning_entity_name(owning_entities_data["owning-entity"]["name"]) + except ResourceNotFound: + owning_entity = OwningEntity.create(owning_entities_data["owning-entity"]["name"], + owning_entities_data["owning-entity"]["id"]) + owning_entity.add_relationship( + Relationship( + related_to="tenant", + related_link=self.tenant.url, + relationship_data=[] + ) + ) + @property def exists(self) -> bool: """Determine if resource already exists or not. diff --git a/onap_data_provider/schemas/infra.schema b/onap_data_provider/schemas/infra.schema index d276755..045806f 100644 --- a/onap_data_provider/schemas/infra.schema +++ b/onap_data_provider/schemas/infra.schema @@ -170,7 +170,7 @@ properties: type: array items: type: object - properities: + properties: tenant-id: type: string cloud-owner: @@ -460,7 +460,7 @@ properties: type: array items: type: object - properities: + properties: owning-entity: type: object properties: @@ -477,7 +477,7 @@ properties: properties: project: type: object - properities: + properties: name: type: string required: @@ -488,10 +488,10 @@ properties: type: array items: type: object - properities: + properties: platform: type: object - properities: + properties: name: type: string required: @@ -505,7 +505,7 @@ properties: properties: line-of-business: type: object - properities: + properties: name: type: string required: @@ -556,7 +556,7 @@ properties: properties: data-dictionaries: type: object - properities: + properties: file-path: type: string required: diff --git a/onap_data_provider/schemas/infra_1_1.schema b/onap_data_provider/schemas/infra_1_1.schema index 8320b74..c5cde66 100644 --- a/onap_data_provider/schemas/infra_1_1.schema +++ b/onap_data_provider/schemas/infra_1_1.schema @@ -19,6 +19,64 @@ properties: - service-description required: - aai-service + owning-entities: &owning_entities + type: array + items: + type: object + properties: + owning-entity: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + required: + - owning-entity + projects: &projects + type: array + items: + type: object + properties: + project: + type: object + properties: + name: + type: string + required: + - name + required: + - project + platforms: + type: array + items: + type: object + properties: + platform: + type: object + properties: + name: + type: string + required: + - name + required: + - platform + lines-of-business: &lines_of_business + type: array + items: + type: object + properties: + line-of-business: + type: object + properties: + name: + type: string + required: + - name + required: + - line-of-business complexes: type: array items: @@ -90,6 +148,8 @@ properties: type: string tenant-context: type: string + lines_of_business: *lines_of_business + owning_entities: *owning_entities required: - tenant-id - tenant-name @@ -138,6 +198,7 @@ properties: required: - availability-zone-name - hypervisor-type + projects: *projects required: - cloud-owner - cloud-region-id @@ -170,7 +231,7 @@ properties: type: array items: type: object - properities: + properties: tenant-id: type: string cloud-owner: @@ -500,62 +561,6 @@ properties: - platform - line_of_business - aai_service - owning-entities: - type: array - items: - type: object - properities: - owning-entity: - type: object - properties: - name: - type: string - required: - - name - required: - - owning-entity - projects: - type: array - items: - type: object - properties: - project: - type: object - properities: - name: - type: string - required: - - name - required: - - project - platforms: - type: array - items: - type: object - properities: - platform: - type: object - properities: - name: - type: string - required: - - name - required: - - platform - lines-of-business: - type: array - items: - type: object - properties: - line-of-business: - type: object - properities: - name: - type: string - required: - - name - required: - - line-of-business msb-k8s-definitions: type: array items: @@ -600,7 +605,7 @@ properties: properties: data-dictionaries: type: object - properities: + properties: file-path: type: string required: diff --git a/requirements.txt b/requirements.txt index 2a85652..1b75fb7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -onapsdk==9.3.0 +onapsdk==10.0.1 PyYAML~=5.4.1 -jsonschema==3.2.0 +jsonschema==4.4.0 diff --git a/samples/cloud-region.yaml b/samples/cloud-region.yaml index 86c7273..f5570af 100644 --- a/samples/cloud-region.yaml +++ b/samples/cloud-region.yaml @@ -2,7 +2,7 @@ # Cloud region resource is one of the biggest to describe (if you want to configure it with OpenStack) # Please fill the data based on your OpenStack instance RC v3 file (ask OpenStack admin). # -odpSchemaVersion: 1.0 +odpSchemaVersion: 1.1 resources: cloud-regions: - cloud-region: @@ -25,3 +25,16 @@ resources: service-url: http://127.0.0.1:5000/v3 cloud-domain: Default default-tenant: default-tenant + projects: + - project: + name: test-project-1234 + tenants: + - tenant-id: "12345" + tenant-name: test-tenant + lines-of-business: + - line-of-business: + name: test-tenant-lob + owning-entities: + - owning-entity: + name: test-oe + id: test-oe diff --git a/setup.py b/setup.py index 42e8334..4b91b99 100644 --- a/setup.py +++ b/setup.py @@ -35,11 +35,12 @@ setuptools.setup( "onap-data-provider=onap_data_provider.data_provider:run", ] }, - install_requires=["onapsdk==9.3.0", "PyYAML~=5.4.1", "jsonschema==3.2.0"], + install_requires=["onapsdk==10.0.1", "PyYAML~=5.4.1", "jsonschema==4.4.0"], classifiers=[ "Development Status :: 5 - Production/Stable", "Programming Language :: Python", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", ], ) diff --git a/tests/test_cloud_region_resource.py b/tests/test_cloud_region_resource.py index b704720..303e1c3 100644 --- a/tests/test_cloud_region_resource.py +++ b/tests/test_cloud_region_resource.py @@ -80,21 +80,22 @@ def test_cloud_region_create(mock_cloud_region_create, mock_exists): "onap_data_provider.resources.cloud_region_resource.CloudRegionResource.cloud_region", new_callable=PropertyMock, ) -@patch("onap_data_provider.resources.cloud_region_resource.Complex.get_all") +@patch("onap_data_provider.resources.cloud_region_resource.Complex.get_by_physical_location_id") def test_cloud_region_resource_link_to_complex( - mock_complex_get_all, mock_cloud_region_property + mock_complex_get_by_physical_location_id, mock_cloud_region_property ): mock_cloud_region_property.return_value.complex = MagicMock() cloud_region_resource = CloudRegionResource(CLOUD_REGION_DATA) cloud_region_resource._link_to_complex("test") - mock_complex_get_all.assert_not_called() + mock_complex_get_by_physical_location_id.assert_not_called() mock_cloud_region_property.return_value.complex = None - mock_complex_get_all.return_value = iter(()) + mock_complex_get_by_physical_location_id.side_effect = ResourceNotFound cloud_region_resource._link_to_complex("test") mock_cloud_region_property.return_value.link_to_complex.assert_not_called() - mock_complex_get_all.return_value = iter([Complex("test")]) + mock_complex_get_by_physical_location_id.side_effect = None + mock_complex_get_by_physical_location_id.return_value = Complex("test") cloud_region_resource._link_to_complex("test") mock_cloud_region_property.return_value.link_to_complex.assert_called_once() -- cgit 1.2.3-korg