From 22664610f99038223f996ef1c1661872a92e4ee4 Mon Sep 17 00:00:00 2001 From: Lukasz Rajewski Date: Thu, 23 Dec 2021 13:40:11 +0100 Subject: [PATCH] [TEST] Basic CNF macro Basic CNF macro added with refactoring that enables debugging under IDE Also SDK upgraded to 9.2 what required adaptation in existing tests Issue-ID: TEST-376 Signed-off-by: Lukasz Rajewski Change-Id: I697857bc0c13e86b88b71c3b46e0c4b59751939c Signed-off-by: mrichomme --- requirements.txt | 6 +- run_basic_cnf_macro.py | 32 +++++ setup.cfg | 1 + .../configuration/basic_clamp_settings.py | 11 +- .../configuration/basic_cnf_macro_settings.py | 78 ++++++++++++ .../configuration/basic_cnf_yaml_settings.py | 34 +++--- .../basic_network_nomulticloud_settings.py | 10 +- .../configuration/basic_onboard_settings.py | 17 ++- .../configuration/basic_vm_macro_settings.py | 15 ++- .../basic_vm_macro_stability_settings.py | 3 +- .../basic_vm_multicloud_yaml_settings.py | 4 +- src/onaptests/configuration/basic_vm_settings.py | 10 +- .../configuration/cba_enrichment_settings.py | 5 +- .../cds_resource_resolution_settings.py | 17 +-- .../clearwater_ims_nomulticloud_settings.py | 10 +- .../configuration/multi_vnf_ubuntu_settings.py | 17 ++- src/onaptests/configuration/pnf_macro_settings.py | 20 ++-- src/onaptests/scenario/basic_cnf_macro.py | 132 +++++++++++++++++++++ src/onaptests/scenario/basic_vm_macro.py | 6 +- src/onaptests/scenario/multi_vnf_macro.py | 4 +- src/onaptests/scenario/pnf_macro.py | 4 +- src/onaptests/steps/base.py | 20 ++++ .../cloud/customer_service_subscription_create.py | 2 +- .../steps/instantiate/k8s_profile_create.py | 12 +- .../steps/instantiate/service_ala_carte.py | 6 +- src/onaptests/steps/instantiate/service_macro.py | 16 ++- .../steps/instantiate/vf_module_ala_carte.py | 4 +- src/onaptests/steps/instantiate/vl_ala_carte.py | 4 +- src/onaptests/steps/instantiate/vnf_ala_carte.py | 4 +- src/onaptests/steps/loop/clamp.py | 4 +- src/onaptests/steps/onboard/cds.py | 4 +- src/onaptests/steps/onboard/clamp.py | 4 +- src/onaptests/steps/onboard/service.py | 4 +- src/onaptests/steps/onboard/vf.py | 4 +- src/onaptests/steps/onboard/vsp.py | 8 +- src/onaptests/steps/reports_collection.py | 8 +- src/onaptests/steps/wrapper/helm_charts.py | 2 +- .../templates/artifacts/basic_cnf_cba_enriched.zip | Bin 0 -> 60824 bytes .../heat-files/basic_cnf_macro/basic_cnf_macro.zip | Bin 0 -> 20627 bytes .../vnf-services/basic_clamp-service.yaml | 2 +- .../templates/vnf-services/basic_cnf-service.yaml | 2 +- .../vnf-services/basic_cnf_macro-service.yaml | 68 +++++++++++ .../vnf-services/basic_onboard-service.yaml.j2 | 2 +- .../templates/vnf-services/basic_vm-service.yaml | 2 +- .../vnf-services/basic_vm_macro-service.yaml | 2 +- .../basic_vm_macro_stability-service.yaml | 4 +- .../vnf-services/clearwater-ims-service.yaml | 2 +- .../vnf-services/multi-vnf-ubuntu-model.yaml.j2 | 2 +- .../templates/vnf-services/pnf-service.yaml | 2 +- .../utils/{simulators.py => resources.py} | 8 ++ tox.ini | 2 + 51 files changed, 481 insertions(+), 159 deletions(-) create mode 100644 run_basic_cnf_macro.py create mode 100644 src/onaptests/configuration/basic_cnf_macro_settings.py create mode 100644 src/onaptests/scenario/basic_cnf_macro.py create mode 100644 src/onaptests/templates/artifacts/basic_cnf_cba_enriched.zip create mode 100644 src/onaptests/templates/heat-files/basic_cnf_macro/basic_cnf_macro.zip create mode 100644 src/onaptests/templates/vnf-services/basic_cnf_macro-service.yaml rename src/onaptests/utils/{simulators.py => resources.py} (67%) diff --git a/requirements.txt b/requirements.txt index c84e334..39ee870 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -xtesting +xtesting==0.91.0 +avionix>=0.4.5 openstacksdk -onapsdk==9.0.0 +onapsdk==9.2.2 jinja2 kubernetes -avionix==0.4.4 \ No newline at end of file diff --git a/run_basic_cnf_macro.py b/run_basic_cnf_macro.py new file mode 100644 index 0000000..e6c1823 --- /dev/null +++ b/run_basic_cnf_macro.py @@ -0,0 +1,32 @@ +import logging.config +import time +import onaptests.utils.exceptions as onap_test_exceptions +from onapsdk.configuration import settings +from onaptests.scenario.basic_cnf_macro import BasicCnfMacro + +if __name__ == "__main__": + # logging configuration for onapsdk, it is not requested for onaptests + # Correction requested in onapsdk to avoid having this duplicate code + logging.config.dictConfig(settings.LOG_CONFIG) + logger = logging.getLogger("Instantiate Apache CNF with macro procedure") + step = BasicCnfMacro(cleanup=settings.CLEANUP_FLAG) + try: + step.execute() + if settings.CLEANUP_FLAG: + logger.info("Starting to clean up in {} seconds".format(settings.CLEANUP_ACTIVITY_TIMER)) + time.sleep(settings.CLEANUP_ACTIVITY_TIMER) + step.cleanup() + except onap_test_exceptions.TestConfigurationException: + logger.error("Ubuntu NSO VM configuration error") + except onap_test_exceptions.ServiceInstantiateException: + logger.error("Ubuntu NSO VM instantiation error") + except onap_test_exceptions.ServiceCleanupException: + logger.error("Ubuntu NSO VM instance cleanup error") + except onap_test_exceptions.VnfInstantiateException: + logger.error("Ubuntu NSO VM Vnf instantiation error") + except onap_test_exceptions.VnfCleanupException: + logger.error("Ubuntu NSO VM Vnf instance cleanup error") + except onap_test_exceptions.VfModuleInstantiateException: + logger.error("Ubuntu NSO VM Module instantiation error") + except onap_test_exceptions.VfModuleCleanupException: + logger.error("Ubuntu NSO VM Module cleanup error") diff --git a/setup.cfg b/setup.cfg index 63444b6..7362a35 100644 --- a/setup.cfg +++ b/setup.cfg @@ -56,3 +56,4 @@ xtesting.testcase = basic_clamp = onaptests.scenario.basic_clamp:BasicClamp cds_resource_resolution = onaptests.scenario.cds_resource_resolution:CDSResourceResolution multi_vnf_ubuntu_macro = onaptests.scenario.multi_vnf_macro:MultiVnfUbuntuMacro + basic_cnf_macro = onaptests.scenario.basic_cnf_macro:BasicCnfMacro diff --git a/src/onaptests/configuration/basic_clamp_settings.py b/src/onaptests/configuration/basic_clamp_settings.py index c26c4e9..3eaad2d 100644 --- a/src/onaptests/configuration/basic_clamp_settings.py +++ b/src/onaptests/configuration/basic_clamp_settings.py @@ -1,5 +1,5 @@ -import sys -from yaml import load +from yaml import load, SafeLoader +from onaptests.utils.resources import get_resource_location from .settings import * # pylint: disable=W0614 @@ -39,14 +39,13 @@ OPERATIONAL_POLICIES = [ # if a yaml file is define, retrieve info from this yaml files # if not declare the parameters in the settings -SERVICE_YAML_TEMPLATE = (sys.path[-1] + "/onaptests/templates/vnf-services/" + - "basic_clamp-service.yaml") -CONFIGURATION_PATH = sys.path[-1] + "/onaptests/configuration/" +SERVICE_YAML_TEMPLATE = get_resource_location("templates/vnf-services/basic_clamp-service.yaml") +CONFIGURATION_PATH = get_resource_location("configuration/") try: # Try to retrieve the SERVICE NAME from the yaml file with open(SERVICE_YAML_TEMPLATE, "r") as yaml_template: - yaml_config_file = load(yaml_template) + yaml_config_file = load(yaml_template, SafeLoader) SERVICE_NAME = next(iter(yaml_config_file.keys())) VF_NAME = SERVICE_NAME except ValueError: diff --git a/src/onaptests/configuration/basic_cnf_macro_settings.py b/src/onaptests/configuration/basic_cnf_macro_settings.py new file mode 100644 index 0000000..4433bf2 --- /dev/null +++ b/src/onaptests/configuration/basic_cnf_macro_settings.py @@ -0,0 +1,78 @@ +import os +from pathlib import Path +from uuid import uuid4 +from yaml import load, SafeLoader + +from onaptests.utils.resources import get_resource_location +import onaptests.utils.exceptions as onap_test_exceptions +from .settings import * # pylint: disable=W0614 + +""" Specific basic_cnf_macro with multicloud-k8s and yaml config scenario.""" +SERVICE_DETAILS = ("Onboarding, distribution and instantiation of a Apache CNF" + + "using macro and native CNF path: cnf-adapter + K8sPlugin") +SERVICE_COMPONENTS = "SDC, DMAAP, AAI, SO, SDNC, CDS, Multicloud K8S" + +CLEANUP_FLAG = True + +# CDS_DD_FILE = Path(get_resource_location("templates/artifacts/dd.json")) +CDS_CBA_UNENRICHED = Path("no_such_file") +CDS_CBA_ENRICHED = Path(get_resource_location("templates/artifacts/basic_cnf_cba_enriched.zip")) + +# This scenario uses multicloud-k8s and not multicloud +# (no registration requested) +USE_MULTICLOUD = False +# Set ONLY_INSTANTIATE to true to run an instantiation without repeating +# onboarding and related AAI configuration (Cloud config) +ONLY_INSTANTIATE = False + +# Relative path to config file to set k8s connectivity information +K8S_CONFIG = get_resource_location("templates/artifacts/config") + +VENDOR_NAME = "basiccnf_macro_vendor" + +CLOUD_REGION_CLOUD_OWNER = "basiccnf-cloud-owner" # must not contain _ +CLOUD_REGION_ID = "k8sregion" +CLOUD_REGION_TYPE = "k8s" +CLOUD_REGION_VERSION = "1.0" +CLOUD_DOMAIN = "Default" +CLOUD_OWNER_DEFINED_TYPE = "t1" + +COMPLEX_PHYSICAL_LOCATION_ID = "lannion" +COMPLEX_DATA_CENTER_CODE = "1234-5" +AVAILABILITY_ZONE_NAME = "basiccnf-availability-zone" +AVAILABILITY_ZONE_TYPE = "nova" + +GLOBAL_CUSTOMER_ID = "basiccnf-macro-customer" + +OWNING_ENTITY = "basicnf_macro_owning_entity" +PROJECT = "basicnf_macro_project" +LINE_OF_BUSINESS = "basicnf_macro_lob" +PLATFORM = "basicnf_macro_platform" + +# The cloud Part +# Assuming a cloud.yaml is available, use the openstack client +# to retrieve cloud info and avoid data duplication +# For basic_cnf, no tenant information is required but some dummy +# information shall be provided by default +# So it is not requested to set OS_TEST_CLOUD +TEST_CLOUD = os.getenv('OS_TEST_CLOUD') +VIM_USERNAME = 'dummy' +VIM_PASSWORD = 'dummy123' +VIM_SERVICE_URL = 'http://10.12.25.2:5000/v3' +TENANT_ID = '123456' +TENANT_NAME = 'dummy_test' + + +SERVICE_YAML_TEMPLATE = Path(get_resource_location("templates/vnf-services/basic_cnf_macro-service.yaml")) + +try: + # Try to retrieve the SERVICE NAME from the yaml file + with open(SERVICE_YAML_TEMPLATE, "r") as yaml_template: + yaml_config_file = load(yaml_template, SafeLoader) + SERVICE_NAME = next(iter(yaml_config_file.keys())) +except (FileNotFoundError, ValueError): + raise onap_test_exceptions.TestConfigurationException + +SERVICE_INSTANCE_NAME = f"basic_cnf_macro_{str(uuid4())}" + +MODEL_YAML_TEMPLATE = None diff --git a/src/onaptests/configuration/basic_cnf_yaml_settings.py b/src/onaptests/configuration/basic_cnf_yaml_settings.py index 38e551c..36b0c3f 100644 --- a/src/onaptests/configuration/basic_cnf_yaml_settings.py +++ b/src/onaptests/configuration/basic_cnf_yaml_settings.py @@ -1,31 +1,28 @@ import os -import openstack -import sys -from yaml import load - +from yaml import load, SafeLoader +from onaptests.utils.resources import get_resource_location import onaptests.utils.exceptions as onap_test_exceptions from .settings import * # pylint: disable=W0614 """ Specific basic_cnf with multicloud-k8s and yaml config scenario.""" SERVICE_DETAILS = ("Onboarding, distribution and instantiation of a CNF" + "using à la carte and Multicloud K8S module") -SERVICE_COMPONENTS="SDC, DMAAP, AAI, SO, SDNC, Multicloud K8S" +SERVICE_COMPONENTS = "SDC, DMAAP, AAI, SO, SDNC, Multicloud K8S" # This scenario uses multicloud-k8s and not multicloud # (no registration requested) USE_MULTICLOUD = False # Set ONLY_INSTANTIATE to true to run an instantiation without repeating # onboarding and related AAI configuration (Cloud config) -ONLY_INSTANTIATE= False +ONLY_INSTANTIATE = False # if a yaml file is define, retrieve info from this yaml files # if not declare the parameters in the settings -SERVICE_YAML_TEMPLATE = (sys.path[-1] + "/onaptests/templates/vnf-services/" + - "basic_cnf-service.yaml") +SERVICE_YAML_TEMPLATE = get_resource_location("templates/vnf-services/basic_cnf-service.yaml") try: # Try to retrieve the SERVICE NAME from the yaml file with open(SERVICE_YAML_TEMPLATE, "r") as yaml_template: - yaml_config_file = load(yaml_template) + yaml_config_file = load(yaml_template, SafeLoader) SERVICE_NAME = next(iter(yaml_config_file.keys())) except (FileNotFoundError, ValueError): raise onap_test_exceptions.TestConfigurationException @@ -37,15 +34,13 @@ CLEANUP_ACTIVITY_TIMER = 10 # Definition of k8s profile version K8S_PROFILE_K8S_VERSION = "1.0" # Relative path to k8s profile artifact in the python package (so under /src) -K8S_PROFILE_ARTIFACT_PATH = (sys.path[-1] + - "/onaptests/templates/artifacts/k8sprof.tar.gz") +K8S_PROFILE_ARTIFACT_PATH = get_resource_location("templates/artifacts/k8sprof.tar.gz") # Relative path to config file to set k8s connectivity information -K8S_CONFIG = (sys.path[-1] + - "/onaptests/templates/artifacts/config") +K8S_CONFIG = get_resource_location("templates/artifacts/config") VENDOR_NAME = "basicnf_vendor" -CLOUD_REGION_CLOUD_OWNER = "basicnf-owner" # must not contain _ +CLOUD_REGION_CLOUD_OWNER = "basicnf-owner" # must not contain _ CLOUD_REGION_ID = "k8sregion" CLOUD_REGION_TYPE = "k8s" CLOUD_REGION_VERSION = "1.0" @@ -73,11 +68,10 @@ SERVICE_INSTANCE_NAME = "basic_cnf_service_instance" # information shall be provided by default # So it is not requested to set OS_TEST_CLOUD TEST_CLOUD = os.getenv('OS_TEST_CLOUD') -cloud = openstack.connect(cloud=TEST_CLOUD) -VIM_USERNAME = cloud.config.auth.get('username','dummy') -VIM_PASSWORD = cloud.config.auth.get('password','dummy123') -VIM_SERVICE_URL = cloud.config.auth.get('auth_url','http://10.12.25.2:5000/v3') -TENANT_ID = cloud.config.auth.get('project_id','123456') -TENANT_NAME = cloud.config.auth.get('project_name','dummy_test') +VIM_USERNAME = 'dummy' +VIM_PASSWORD = 'dummy123' +VIM_SERVICE_URL = 'http://10.12.25.2:5000/v3' +TENANT_ID = '123456' +TENANT_NAME = 'dummy_test' MODEL_YAML_TEMPLATE = None diff --git a/src/onaptests/configuration/basic_network_nomulticloud_settings.py b/src/onaptests/configuration/basic_network_nomulticloud_settings.py index ab9e5ab..add6175 100644 --- a/src/onaptests/configuration/basic_network_nomulticloud_settings.py +++ b/src/onaptests/configuration/basic_network_nomulticloud_settings.py @@ -1,8 +1,7 @@ import os import openstack -import sys -from yaml import load - +from yaml import load, SafeLoader +from onaptests.utils.resources import get_resource_location import onaptests.utils.exceptions as onap_test_exceptions from .settings import * # pylint: disable=W0614 @@ -19,13 +18,12 @@ ONLY_INSTANTIATE= False # if a yaml file is define, retrieve info from this yaml files # if not declare the parameters in the settings -SERVICE_YAML_TEMPLATE = (sys.path[-1] + "/onaptests/templates/vnf-services/" + - "basic_network-service.yaml") +SERVICE_YAML_TEMPLATE = get_resource_location("templates/vnf-services/basic_network-service.yaml") try: # Try to retrieve the SERVICE NAME from the yaml file with open(SERVICE_YAML_TEMPLATE, "r") as yaml_template: - yaml_config_file = load(yaml_template) + yaml_config_file = load(yaml_template, SafeLoader) SERVICE_NAME = next(iter(yaml_config_file.keys())) except (FileNotFoundError, ValueError): raise onap_test_exceptions.TestConfigurationException diff --git a/src/onaptests/configuration/basic_onboard_settings.py b/src/onaptests/configuration/basic_onboard_settings.py index 2fa1820..8975fa8 100644 --- a/src/onaptests/configuration/basic_onboard_settings.py +++ b/src/onaptests/configuration/basic_onboard_settings.py @@ -1,14 +1,16 @@ -import sys import random import string -from yaml import load +from yaml import load, SafeLoader from jinja2 import Environment, PackageLoader + import onaptests.utils.exceptions as onap_test_exceptions +from onaptests.utils.resources import get_resource_location from .settings import * # pylint: disable=W0614 """ Creation of service to onboard""" + # We need to create a service file with a random service name, # to be sure that we force onboarding def generate_service_config_yaml_file(): @@ -28,10 +30,7 @@ def generate_service_config_yaml_file(): rendered_template = template.render(service_name=service_name) - file_name = (sys.path[-1] + "/onaptests/templates/vnf-services/" + - "basic-onboard-service.yaml") - - with open(file_name, 'w+') as file_to_write: + with open(SERVICE_YAML_TEMPLATE, 'w+') as file_to_write: file_to_write.write(rendered_template) """Basic onboard service to only onboard a service in SDC""" @@ -48,14 +47,14 @@ SERVICE_COMPONENTS="SDC" # if a yaml file is define, retrieve info from this yaml files # if not declare the parameters in the settings + +SERVICE_YAML_TEMPLATE = get_resource_location("templates/vnf-services/basic-onboard-service.yaml") generate_service_config_yaml_file() -SERVICE_YAML_TEMPLATE = (sys.path[-1] + "/onaptests/templates/vnf-services/" + - "basic-onboard-service.yaml") try: # Try to retrieve the SERVICE NAME from the yaml file with open(SERVICE_YAML_TEMPLATE, "r") as yaml_template: - yaml_config_file = load(yaml_template) + yaml_config_file = load(yaml_template, SafeLoader) SERVICE_NAME = next(iter(yaml_config_file.keys())) except (FileNotFoundError, ValueError): raise onap_test_exceptions.TestConfigurationException diff --git a/src/onaptests/configuration/basic_vm_macro_settings.py b/src/onaptests/configuration/basic_vm_macro_settings.py index 2784f86..522c66a 100644 --- a/src/onaptests/configuration/basic_vm_macro_settings.py +++ b/src/onaptests/configuration/basic_vm_macro_settings.py @@ -2,18 +2,18 @@ import os import openstack from pathlib import Path from uuid import uuid4 - -from yaml import load +from yaml import load, SafeLoader import onaptests.utils.exceptions as onap_test_exceptions +from onaptests.utils.resources import get_resource_location from .settings import * # pylint: disable=W0614 CLEANUP_FLAG = True -CDS_DD_FILE = Path(Path(__file__).parent.parent, "templates/artifacts/dd.json") -CDS_CBA_UNENRICHED = Path(Path(__file__).parent.parent, "templates/artifacts/basic_vm_cba.zip") -CDS_CBA_ENRICHED = "/tmp/BASIC_VM_enriched.zip" +CDS_DD_FILE = Path(get_resource_location("templates/artifacts/dd.json")) +CDS_CBA_UNENRICHED = Path(get_resource_location("templates/artifacts/basic_vm_cba.zip")) +CDS_CBA_ENRICHED = Path("/tmp/BASIC_VM_enriched.zip") ONLY_INSTANTIATE = False USE_MULTICLOUD = False @@ -47,13 +47,12 @@ PROJECT = "basicvm-project" LINE_OF_BUSINESS = "basicvm-lob" PLATFORM = "basicvm-platform" CLOUD_DOMAIN = "Default" -SERVICE_YAML_TEMPLATE = Path(Path(__file__).parent.parent, "templates/vnf-services/" + - "basic_vm_macro-service.yaml") +SERVICE_YAML_TEMPLATE = Path(get_resource_location("templates/vnf-services/basic_vm_macro-service.yaml")) try: # Try to retrieve the SERVICE NAME from the yaml file with open(SERVICE_YAML_TEMPLATE, "r") as yaml_template: - yaml_config_file = load(yaml_template) + yaml_config_file = load(yaml_template, SafeLoader) SERVICE_NAME = next(iter(yaml_config_file.keys())) except (FileNotFoundError, ValueError): raise onap_test_exceptions.TestConfigurationException diff --git a/src/onaptests/configuration/basic_vm_macro_stability_settings.py b/src/onaptests/configuration/basic_vm_macro_stability_settings.py index b2fe037..67a423c 100644 --- a/src/onaptests/configuration/basic_vm_macro_stability_settings.py +++ b/src/onaptests/configuration/basic_vm_macro_stability_settings.py @@ -1,5 +1,4 @@ from .basic_vm_macro_settings import * # pylint: disable=W0614 -SERVICE_YAML_TEMPLATE = Path(Path(__file__).parent.parent, "templates/vnf-services/" + - "basic_vm_macro_stability-service.yaml") +SERVICE_YAML_TEMPLATE = Path(get_resource_location("templates/vnf-services/basic_vm_macro_stability-service.yaml")) MODEL_YAML_TEMPLATE = None diff --git a/src/onaptests/configuration/basic_vm_multicloud_yaml_settings.py b/src/onaptests/configuration/basic_vm_multicloud_yaml_settings.py index 51c74e5..cb16d81 100644 --- a/src/onaptests/configuration/basic_vm_multicloud_yaml_settings.py +++ b/src/onaptests/configuration/basic_vm_multicloud_yaml_settings.py @@ -1,4 +1,4 @@ -import sys +from onaptests.utils.resources import get_resource_location from .settings import * # pylint: disable=W0614 """ Specific Basic VM with multicloud and yaml config scenario.""" @@ -40,5 +40,5 @@ PLATFORM = "sdktests_platform" SERVICE_INSTANCE_NAME = "sdktests_service_instance_name" -SERVICE_YAML_TEMPLATE = sys.path[-1] + "/onaptests/templates/vnf-services/basic_vm-service.yaml" +SERVICE_YAML_TEMPLATE = get_resource_location("templates/vnf-services/basic_vm-service.yaml") MODEL_YAML_TEMPLATE = None diff --git a/src/onaptests/configuration/basic_vm_settings.py b/src/onaptests/configuration/basic_vm_settings.py index 2c7d85f..0b33ec1 100644 --- a/src/onaptests/configuration/basic_vm_settings.py +++ b/src/onaptests/configuration/basic_vm_settings.py @@ -1,8 +1,7 @@ import os import openstack -import sys -from yaml import load - +from yaml import load, SafeLoader +from onaptests.utils.resources import get_resource_location import onaptests.utils.exceptions as onap_test_exceptions from .settings import * # pylint: disable=W0614 @@ -20,13 +19,12 @@ ONLY_INSTANTIATE= False # if a yaml file is define, retrieve info from this yaml files # if not declare the parameters in the settings -SERVICE_YAML_TEMPLATE = (sys.path[-1] + "/onaptests/templates/vnf-services/" + - "basic_vm-service.yaml") +SERVICE_YAML_TEMPLATE = get_resource_location("templates/vnf-services/basic_vm-service.yaml") try: # Try to retrieve the SERVICE NAME from the yaml file with open(SERVICE_YAML_TEMPLATE, "r") as yaml_template: - yaml_config_file = load(yaml_template) + yaml_config_file = load(yaml_template, SafeLoader) SERVICE_NAME = next(iter(yaml_config_file.keys())) except (FileNotFoundError, ValueError): raise onap_test_exceptions.TestConfigurationException diff --git a/src/onaptests/configuration/cba_enrichment_settings.py b/src/onaptests/configuration/cba_enrichment_settings.py index 0770d8d..2d05cd2 100644 --- a/src/onaptests/configuration/cba_enrichment_settings.py +++ b/src/onaptests/configuration/cba_enrichment_settings.py @@ -1,11 +1,12 @@ from pathlib import Path +from onaptests.utils.resources import get_resource_location from .settings import * # pylint: disable=W0614 SERVICE_NAME = "CDS blueprint enrichment" CLEANUP_FLAG = True -CDS_DD_FILE = Path(Path(__file__).parent.parent, "templates/artifacts/dd.json") -CDS_CBA_UNENRICHED = Path(Path(__file__).parent.parent, "templates/artifacts/PNF_DEMO.zip") +CDS_DD_FILE = Path(get_resource_location("templates/artifacts/dd.json")) +CDS_CBA_UNENRICHED = Path(get_resource_location("templates/artifacts/PNF_DEMO.zip")) CDS_CBA_ENRICHED = "/tmp/PNF_DEMO_enriched.zip" diff --git a/src/onaptests/configuration/cds_resource_resolution_settings.py b/src/onaptests/configuration/cds_resource_resolution_settings.py index 16e23a6..b18d2ac 100644 --- a/src/onaptests/configuration/cds_resource_resolution_settings.py +++ b/src/onaptests/configuration/cds_resource_resolution_settings.py @@ -1,6 +1,7 @@ from pathlib import Path from uuid import uuid4 +from onaptests.utils.resources import get_resource_location from .settings import * # pylint: disable=W0614 CLEANUP_FLAG = True @@ -12,15 +13,15 @@ CLOUD_REGION_VERSION = "1.0" CLOUD_OWNER_DEFINED_TYPE = "N/A" COMPLEX_PHYSICAL_LOCATION_ID = "sdktests" -MSB_K8S_DEFINITION_ATRIFACT_FILE_PATH = Path(Path(__file__).parent.parent, - "templates/artifacts/cds-resource-resolution/cds-mock-server.tar.gz") +MSB_K8S_DEFINITION_ATRIFACT_FILE_PATH = Path(get_resource_location( + "templates/artifacts/cds-resource-resolution/cds-mock-server.tar.gz")) MSB_K8S_RB_NAME = f"cds-ms-rb-{str(uuid4())}" MSB_K8S_RB_VERSION = "v1" -MSB_K8S_PROFILE_ARTIFACT_FILE_PATH = Path(Path(__file__).parent.parent, - "templates/artifacts/profile.tar.gz") +MSB_K8S_PROFILE_ARTIFACT_FILE_PATH = Path(get_resource_location( + "templates/artifacts/profile.tar.gz")) MSB_K8S_PROFILE_NAME = f"cds-ms-prof-{str(uuid4())}" K8S_VERSION = "1.0" -K8S_CONFIG = str(Path(Path(__file__).parent.parent, "templates/artifacts/config")) +K8S_CONFIG = get_resource_location("templates/artifacts/config") K8S_ADDITIONAL_RESOURCES_NAMESPACE = "onap-tests" CDS_MOCKSERVER_EXPECTATIONS = [ { @@ -55,9 +56,9 @@ CDS_MOCKSERVER_EXPECTATIONS = [ } ] -CDS_DD_FILE = Path(Path(__file__).parent.parent, "templates/artifacts/cds-resource-resolution/dd.json") -CDS_CBA_UNENRICHED = Path(Path(__file__).parent.parent, "templates/artifacts/cds-resource-resolution/resource-resolution.zip") -CDS_CBA_ENRICHED = "/tmp/resource-resolution-enriched.zip" +CDS_DD_FILE = Path(get_resource_location("templates/artifacts/cds-resource-resolution/dd.json")) +CDS_CBA_UNENRICHED = Path(get_resource_location("templates/artifacts/cds-resource-resolution/resource-resolution.zip")) +CDS_CBA_ENRICHED = Path("/tmp/resource-resolution-enriched.zip") CDS_WORKFLOW_NAME = "resource-resolution" CDS_WORKFLOW_INPUT = { "template-prefix": [ diff --git a/src/onaptests/configuration/clearwater_ims_nomulticloud_settings.py b/src/onaptests/configuration/clearwater_ims_nomulticloud_settings.py index d20d9ff..5803df3 100644 --- a/src/onaptests/configuration/clearwater_ims_nomulticloud_settings.py +++ b/src/onaptests/configuration/clearwater_ims_nomulticloud_settings.py @@ -1,8 +1,7 @@ import os -import sys import openstack -from yaml import load - +from yaml import load, SafeLoader +from onaptests.utils.resources import get_resource_location from .settings import * # pylint: disable=W0614 """ Specific clearwater IMS without multicloud.""" @@ -21,13 +20,12 @@ VF_NAME = "clearwater-ims_ubuntu_vf" VSP_NAME = "clearwater-ims_ubuntu_vsp" # if a yaml file is define, retrieve info from this yaml files # if not declare the parameters in the settings -SERVICE_YAML_TEMPLATE = (sys.path[-1] + "/onaptests/templates/vnf-services/" + - "clearwater-ims-service.yaml") +SERVICE_YAML_TEMPLATE = get_resource_location("templates/vnf-services/clearwater-ims-service.yaml") try: # Try to retrieve the SERVICE NAME from the yaml file with open(SERVICE_YAML_TEMPLATE, "r") as yaml_template: - yaml_config_file = load(yaml_template) + yaml_config_file = load(yaml_template, SafeLoader) SERVICE_NAME = next(iter(yaml_config_file.keys())) except ValueError: SERVICE_NAME = "" # Fill me diff --git a/src/onaptests/configuration/multi_vnf_ubuntu_settings.py b/src/onaptests/configuration/multi_vnf_ubuntu_settings.py index 47795fd..bb7b8b5 100644 --- a/src/onaptests/configuration/multi_vnf_ubuntu_settings.py +++ b/src/onaptests/configuration/multi_vnf_ubuntu_settings.py @@ -1,9 +1,9 @@ import uuid import os -import sys from pathlib import Path import openstack from jinja2 import Environment, PackageLoader +from onaptests.utils.resources import get_resource_location from .settings import * # pylint: disable=W0614 VNF_FILENAME_PREFIX = "multi-vnf-ubuntu" @@ -23,8 +23,7 @@ def generate_service_config_yaml_file(filename): rendered_template = template.render(service_name=SERVICE_NAME) - file_name = (sys.path[-1] + "/onaptests/templates/vnf-services/" + - f"{filename}.yaml") + file_name = get_resource_location(f"templates/vnf-services/{filename}.yaml") with open(file_name, 'w+') as file_to_write: file_to_write.write(rendered_template) @@ -32,8 +31,8 @@ def generate_service_config_yaml_file(filename): CLEANUP_FLAG = True -CDS_DD_FILE = Path(Path(__file__).parent.parent, "templates/artifacts/dd_nso_ubuntu.json") -CDS_CBA_UNENRICHED = Path(Path(__file__).parent.parent, "templates/artifacts/nso_ubuntuvnf.zip") +CDS_DD_FILE = Path(get_resource_location("templates/artifacts/dd_nso_ubuntu.json")) +CDS_CBA_UNENRICHED = Path(get_resource_location("templates/artifacts/nso_ubuntuvnf.zip")) CDS_CBA_ENRICHED = "/tmp/UBUNTUVNF_enriched.zip" ONLY_INSTANTIATE = False @@ -69,11 +68,11 @@ CLOUD_DOMAIN = "Default" VENDOR_NAME = 'ubuntu_xtesting_vendor' -SERVICE_YAML_TEMPLATE = Path(Path(__file__).parent.parent, "templates/vnf-services/" + - f"{VNF_FILENAME_PREFIX}-service.yaml") +SERVICE_YAML_TEMPLATE = Path(get_resource_location("templates/vnf-services/" + + f"{VNF_FILENAME_PREFIX}-service.yaml")) -MODEL_YAML_TEMPLATE = Path(Path(__file__).parent.parent, "templates/vnf-services/" + - f"{VNF_FILENAME_PREFIX}-model.yaml") +MODEL_YAML_TEMPLATE = Path(get_resource_location("templates/vnf-services/" + + f"{VNF_FILENAME_PREFIX}-model.yaml")) generate_service_config_yaml_file(f"{VNF_FILENAME_PREFIX}-service") diff --git a/src/onaptests/configuration/pnf_macro_settings.py b/src/onaptests/configuration/pnf_macro_settings.py index eaca93a..5f2b98c 100644 --- a/src/onaptests/configuration/pnf_macro_settings.py +++ b/src/onaptests/configuration/pnf_macro_settings.py @@ -1,6 +1,7 @@ from pathlib import Path from uuid import uuid4 +from onaptests.utils.resources import get_resource_location from .settings import * # pylint: disable=W0614 ONLY_INSTANTIATE = False @@ -10,13 +11,10 @@ USE_MULTICLOUD = False VENDOR_NAME = "pnf_macro_vendor" SERVICE_NAME = "test_pnf_macro" SERVICE_INSTANCE_NAME = "TestPNFMacroInstantiation" -SERVICE_YAML_TEMPLATE = Path(Path(__file__).parent.parent, - "templates/vnf-services/pnf-service.yaml") +SERVICE_YAML_TEMPLATE = Path(get_resource_location("templates/vnf-services/pnf-service.yaml")) -CDS_DD_FILE = Path(Path(__file__).parent.parent, - "templates/artifacts/dd.json") -CDS_CBA_UNENRICHED = Path(Path(__file__).parent.parent, - "templates/artifacts/PNF_DEMO.zip") +CDS_DD_FILE = Path(get_resource_location("templates/artifacts/dd.json")) +CDS_CBA_UNENRICHED = Path(get_resource_location("templates/artifacts/PNF_DEMO.zip")) CDS_CBA_ENRICHED = "/tmp/PNF_DEMO_enriched.zip" CLOUD_REGION_CLOUD_OWNER = "basicnf-owner" # must not contain _ @@ -33,18 +31,16 @@ PLATFORM = "pnf_macro_platform" INSTANTIATION_TIMEOUT = 600 -MSB_K8S_DEFINITION_ATRIFACT_FILE_PATH = Path(Path(__file__).parent.parent, - "templates/artifacts/pnf-simulator.tar.gz") +MSB_K8S_DEFINITION_ATRIFACT_FILE_PATH = Path(get_resource_location("templates/artifacts/pnf-simulator.tar.gz")) MSB_K8S_RB_NAME = f"pnf-cnf-rb-{str(uuid4())}" MSB_K8S_RB_VERSION = "v1" -MSB_K8S_PROFILE_ARTIFACT_FILE_PATH = Path(Path(__file__).parent.parent, - "templates/artifacts/profile.tar.gz") +MSB_K8S_PROFILE_ARTIFACT_FILE_PATH = Path(get_resource_location("templates/artifacts/profile.tar.gz")) MSB_K8S_PROFILE_NAME = f"pnf-cnf-profile-{str(uuid4())}" K8S_VERSION = "1.0" -K8S_CONFIG = str(Path(Path(__file__).parent.parent, "templates/artifacts/config")) +K8S_CONFIG = get_resource_location("templates/artifacts/config") K8S_ADDITIONAL_RESOURCES_NAMESPACE = "onap-tests" -SERVICE_INSTANCE_NAME = "TestPNFMacroInstantiation" +SERVICE_INSTANCE_NAME = f"TestPNFMacroInstantiation_{str(uuid4())}" DCAE_VES_COLLECTOR_POD_NAME = "dcae-ves-collector" PNF_WAIT_TIME = 60.0 diff --git a/src/onaptests/scenario/basic_cnf_macro.py b/src/onaptests/scenario/basic_cnf_macro.py new file mode 100644 index 0000000..2784782 --- /dev/null +++ b/src/onaptests/scenario/basic_cnf_macro.py @@ -0,0 +1,132 @@ +"""Instantiate basic cnf using SO macro flow.""" +import logging +import time +from yaml import load, SafeLoader + +from onapsdk.configuration import settings +from onapsdk.exceptions import SDKException +from xtesting.core import testcase + +from onaptests.steps.base import YamlTemplateBaseStep +from onaptests.steps.onboard.cds import CbaPublishStep +from onaptests.utils.exceptions import OnapTestException +from onaptests.steps.instantiate.service_macro import YamlTemplateServiceMacroInstantiateStep + + +class BasicCnfMacroStep(YamlTemplateBaseStep): + + def __init__(self, cleanup=False): + """Initialize step. + + Substeps: + - CbaPublishStep + - YamlTemplateServiceMacroInstantiateStep. + """ + super().__init__(cleanup=cleanup) + self._yaml_template: dict = None + self.add_step(CbaPublishStep( + cleanup=cleanup + )) + self.add_step(YamlTemplateServiceMacroInstantiateStep( + cleanup=cleanup + )) + + @property + def description(self) -> str: + """Step description. + + Used for reports + + Returns: + str: Step description + + """ + return "Basic CNF macro scenario step" + + @property + def component(self) -> str: + """Component name. + + Name of component which step is related with. + Most is the name of ONAP component. + + Returns: + str: Component name + + """ + return "PythonSDK-tests" + + @property + def yaml_template(self) -> dict: + """YAML template abstract property. + + Every YAML template step need to implement that property. + + Returns: + dict: YAML template + + """ + if not self._yaml_template: + with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: + self._yaml_template: dict = load(yaml_template, SafeLoader) + return self._yaml_template + + @property + def model_yaml_template(self) -> dict: + return {} + + @property + def service_name(self) -> dict: + """Service name. + + Get from YAML template. + + Returns: + str: Service name + + """ + return next(iter(self.yaml_template.keys())) + + @property + def service_instance_name(self) -> str: + """Service instance name. + + Returns: + str: Service instance name + + """ + return settings.SERVICE_INSTANCE_NAME + + +class BasicCnfMacro(testcase.TestCase): + """Instantiate a basic cnf macro.""" + + __logger = logging.getLogger() + + def __init__(self, **kwargs): + """Init Basic Cnf Macro use case.""" + if "case_name" not in kwargs: + kwargs["case_name"] = 'basic_cnf_macro' + super().__init__(**kwargs) + self.__logger.debug("Basic Cnf macro init started") + self.test = BasicCnfMacroStep(cleanup=settings.CLEANUP_FLAG) + + def run(self): + """Run basic cnf macro test.""" + self.start_time = time.time() + try: + self.test.execute() + self.test.cleanup() + self.result = 100 + except OnapTestException as exc: + self.result = 0 + self.__logger.error(exc.error_message) + except SDKException: + self.result = 0 + self.__logger.error("SDK Exception") + finally: + self.stop_time = time.time() + + def clean(self): + """Generate report.""" + self.test.reports_collection.generate_report() diff --git a/src/onaptests/scenario/basic_vm_macro.py b/src/onaptests/scenario/basic_vm_macro.py index 8bbf0b7..b849831 100644 --- a/src/onaptests/scenario/basic_vm_macro.py +++ b/src/onaptests/scenario/basic_vm_macro.py @@ -1,7 +1,7 @@ """Instantiate basic vm using SO macro flow.""" import logging import time -from yaml import load +from yaml import load, SafeLoader from onapsdk.configuration import settings from onapsdk.exceptions import SDKException @@ -20,7 +20,7 @@ class BasicVmMacroStep(YamlTemplateBaseStep): Substeps: - CbaPublishStep - - YamlTemplateServiceAlaCarteInstantiateStep. + - YamlTemplateServiceMacroInstantiateStep. """ super().__init__(cleanup=cleanup) self._yaml_template: dict = None @@ -68,7 +68,7 @@ class BasicVmMacroStep(YamlTemplateBaseStep): """ if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template @property diff --git a/src/onaptests/scenario/multi_vnf_macro.py b/src/onaptests/scenario/multi_vnf_macro.py index 404c785..41833e6 100644 --- a/src/onaptests/scenario/multi_vnf_macro.py +++ b/src/onaptests/scenario/multi_vnf_macro.py @@ -2,7 +2,7 @@ import logging import time -from yaml import load +from yaml import load, SafeLoader from onapsdk.configuration import settings from onapsdk.exceptions import SDKException @@ -70,7 +70,7 @@ class MultiVnfUbuntuMacroStep(YamlTemplateBaseStep): """ if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template @property diff --git a/src/onaptests/scenario/pnf_macro.py b/src/onaptests/scenario/pnf_macro.py index 7b7c219..931a332 100644 --- a/src/onaptests/scenario/pnf_macro.py +++ b/src/onaptests/scenario/pnf_macro.py @@ -1,7 +1,7 @@ """Instantiate service with PNF using SO macro flow.""" import logging import time -from yaml import load +from yaml import load, SafeLoader from xtesting.core import testcase from onapsdk.configuration import settings @@ -72,7 +72,7 @@ class PnfMacroScenarioStep(YamlTemplateBaseStep): """ if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template @property diff --git a/src/onaptests/steps/base.py b/src/onaptests/steps/base.py index 97c9159..b7651bb 100644 --- a/src/onaptests/steps/base.py +++ b/src/onaptests/steps/base.py @@ -168,6 +168,13 @@ class BaseStep(ABC): try: if cleanup: self._start_cleanup_time = time.time() + self._logger.info("*****************************************************") + self._logger.info(f"START [{self.component}] {self.name} cleanup: {self.description}") + self._logger.info("*****************************************************") + else: + self._logger.info("*****************************************************") + self._logger.info(f"START [{self.component}] {self.name}: {self.description}") + self._logger.info("*****************************************************") execution_status: Optional[ReportStepStatus] = None ret = fun(self, *args, **kwargs) execution_status = ReportStepStatus.PASS @@ -180,12 +187,18 @@ class BaseStep(ABC): raise finally: if cleanup: + self._logger.info("*****************************************************") + self._logger.info(f"STOP [{self.component}] {self.name} cleanup: {self.description}") + self._logger.info("*****************************************************") self._cleanup_report = Report( step_description=f"[{self.component}] {self.name} cleanup: {self.description}", step_execution_status=execution_status, step_execution_duration=time.time() - self._start_cleanup_time ) else: + self._logger.info("*****************************************************") + self._logger.info(f"STOP [{self.component}] {self.name}: {self.description}") + self._logger.info("*****************************************************") if not self._start_execution_time: if execution_status != ReportStepStatus.NOT_EXECUTED: self._logger.error("No execution start time saved for %s step. Fix it by call `super.execute()` " @@ -210,6 +223,10 @@ class BaseStep(ABC): step.execute() except (OnapTestException, SDKException) as substep_err: raise SubstepExecutionException from substep_err + if self._steps: + self._logger.info("*****************************************************") + self._logger.info(f"CONTINUE [{self.component}] {self.name}: {self.description}") + self._logger.info("*****************************************************") self._start_execution_time = time.time() def cleanup(self) -> None: @@ -218,6 +235,9 @@ class BaseStep(ABC): Not all steps has to have cleanup method """ + self._logger.info("*****************************") + self._logger.info("Start Cleanup step: " + self.name) + self._logger.info("*****************************") if self._cleanup: for step in self._steps: try: diff --git a/src/onaptests/steps/cloud/customer_service_subscription_create.py b/src/onaptests/steps/cloud/customer_service_subscription_create.py index b318dc7..67de141 100644 --- a/src/onaptests/steps/cloud/customer_service_subscription_create.py +++ b/src/onaptests/steps/cloud/customer_service_subscription_create.py @@ -39,4 +39,4 @@ class CustomerServiceSubscriptionCreateStep(BaseStep): super().execute() service = Service(name=settings.SERVICE_NAME) customer = Customer.get_by_global_customer_id(settings.GLOBAL_CUSTOMER_ID) - customer.subscribe_service(service) + customer.subscribe_service(service.name) diff --git a/src/onaptests/steps/instantiate/k8s_profile_create.py b/src/onaptests/steps/instantiate/k8s_profile_create.py index d09d924..a5c8552 100644 --- a/src/onaptests/steps/instantiate/k8s_profile_create.py +++ b/src/onaptests/steps/instantiate/k8s_profile_create.py @@ -1,6 +1,6 @@ from typing import Iterable from uuid import uuid4 -from yaml import load +from yaml import load, SafeLoader from onapsdk.aai.business import Customer, ServiceInstance, ServiceSubscription from onapsdk.configuration import settings @@ -48,7 +48,7 @@ class K8SProfileStep(BaseStep): if self.is_root: if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template return self.parent.yaml_template @@ -124,8 +124,8 @@ class K8SProfileStep(BaseStep): for vf_module in vnf_instance.vnf.vf_modules: # Define profile (rb_profile) for resource bundle definition # Retrieve resource bundle definition (rbdef) corresponding to vf module - rbdef_name = vf_module.metadata["vfModuleModelInvariantUUID"] - rbdef_version = vf_module.metadata["vfModuleModelCustomizationUUID"] + rbdef_name = vf_module.model_invariant_uuid + rbdef_version = vf_module.model_customization_id rbdef = Definition.get_definition_by_name_version(rbdef_name, rbdef_version) # Get k8s profile name from yaml service template vnf_parameters = self.get_vnf_parameters(vnf_instance.vnf.name) @@ -160,8 +160,8 @@ class K8SProfileStep(BaseStep): # possible to have several modules for 1 VNF for vf_module in vnf_instance.vnf.vf_modules: # Retrieve resource bundle definition (rbdef) corresponding to vf module - rbdef_name = vf_module.metadata["vfModuleModelInvariantUUID"] - rbdef_version = vf_module.metadata["vfModuleModelCustomizationUUID"] + rbdef_name = vf_module.model_invariant_uuid + rbdef_version = vf_module.model_customization_id rbdef = Definition.get_definition_by_name_version(rbdef_name, rbdef_version) # Get k8s profile name from yaml service template vnf_parameters = self.get_vnf_parameters(vnf_instance.vnf.name) diff --git a/src/onaptests/steps/instantiate/service_ala_carte.py b/src/onaptests/steps/instantiate/service_ala_carte.py index 3407e8e..a2e1812 100644 --- a/src/onaptests/steps/instantiate/service_ala_carte.py +++ b/src/onaptests/steps/instantiate/service_ala_carte.py @@ -1,6 +1,6 @@ import time from uuid import uuid4 -from yaml import load +from yaml import load, SafeLoader from onapsdk.aai.cloud_infrastructure import CloudRegion, Tenant from onapsdk.aai.business import Customer, ServiceInstance, ServiceSubscription @@ -130,7 +130,7 @@ class YamlTemplateServiceAlaCarteInstantiateStep(YamlTemplateBaseStep): if self.is_root: if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template return self.parent.yaml_template @@ -188,6 +188,7 @@ class YamlTemplateServiceAlaCarteInstantiateStep(YamlTemplateBaseStep): super().execute() service = Service(self.service_name) customer: Customer = Customer.get_by_global_customer_id(settings.GLOBAL_CUSTOMER_ID) + service_subscription: ServiceSubscription = customer.get_service_subscription_by_service_type(service.name) cloud_region: CloudRegion = CloudRegion.get_by_id( cloud_owner=settings.CLOUD_REGION_CLOUD_OWNER, cloud_region_id=settings.CLOUD_REGION_ID, @@ -230,6 +231,7 @@ class YamlTemplateServiceAlaCarteInstantiateStep(YamlTemplateBaseStep): customer, owning_entity, settings.PROJECT, + service_subscription, service_instance_name=self.service_instance_name ) try: diff --git a/src/onaptests/steps/instantiate/service_macro.py b/src/onaptests/steps/instantiate/service_macro.py index b169049..dc2ce89 100644 --- a/src/onaptests/steps/instantiate/service_macro.py +++ b/src/onaptests/steps/instantiate/service_macro.py @@ -3,7 +3,7 @@ import time from typing import List from uuid import uuid4 from onapsdk.aai.business.service import ServiceInstance -from yaml import load +from yaml import load, SafeLoader from onapsdk.aai.business.customer import Customer, ServiceSubscription from onapsdk.aai.business.owning_entity import OwningEntity @@ -13,7 +13,6 @@ from onapsdk.configuration import settings from onapsdk.exceptions import ResourceNotFound from onapsdk.sdc.service import Service from onapsdk.so.instantiation import InstantiationParameter, ServiceInstantiation, VfmoduleParameters, VnfParameters, SoService -from onapsdk.vid import LineOfBusiness, Platform, Project from onaptests.steps.cloud.customer_service_subscription_create import CustomerServiceSubscriptionCreateStep import onaptests.utils.exceptions as onap_test_exceptions @@ -73,7 +72,7 @@ class YamlTemplateServiceMacroInstantiateStep(YamlTemplateBaseStep): if self.is_root: if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template return self.parent.yaml_template @@ -144,6 +143,7 @@ class YamlTemplateServiceMacroInstantiateStep(YamlTemplateBaseStep): super().execute() service = Service(self.service_name) customer: Customer = Customer.get_by_global_customer_id(settings.GLOBAL_CUSTOMER_ID) + service_subscription: ServiceSubscription = customer.get_service_subscription_by_service_type(service.name) if any( filter(lambda x: x in self.yaml_template[self.service_name].keys(), ["vnfs", "networks"])): @@ -161,9 +161,6 @@ class YamlTemplateServiceMacroInstantiateStep(YamlTemplateBaseStep): except ResourceNotFound: self._logger.info("Owning entity not found, create it") owning_entity = OwningEntity.create(settings.OWNING_ENTITY) - vid_project: Project = Project(settings.PROJECT) - line_of_business: LineOfBusiness = LineOfBusiness(settings.LINE_OF_BUSINESS) - platform: Platform = Platform(settings.PLATFORM) # Before instantiating, be sure that the service has been distributed self._logger.info("******** Check Service Distribution *******") @@ -210,11 +207,12 @@ class YamlTemplateServiceMacroInstantiateStep(YamlTemplateBaseStep): sdc_service=service, customer=customer, owning_entity=owning_entity, - project=vid_project, - line_of_business=line_of_business, - platform=platform, + project=settings.PROJECT, + line_of_business=settings.LINE_OF_BUSINESS, + platform=settings.PLATFORM, cloud_region=cloud_region, tenant=tenant, + service_subscription=service_subscription, service_instance_name=self.service_instance_name, vnf_parameters=vnf_params_list, enable_multicloud=settings.USE_MULTICLOUD, diff --git a/src/onaptests/steps/instantiate/vf_module_ala_carte.py b/src/onaptests/steps/instantiate/vf_module_ala_carte.py index af569fe..38bdee9 100644 --- a/src/onaptests/steps/instantiate/vf_module_ala_carte.py +++ b/src/onaptests/steps/instantiate/vf_module_ala_carte.py @@ -1,6 +1,6 @@ from typing import Iterable from uuid import uuid4 -from yaml import load +from yaml import load, SafeLoader from onapsdk.aai.cloud_infrastructure import CloudRegion, Tenant from onapsdk.aai.business import Customer, ServiceInstance, ServiceSubscription @@ -56,7 +56,7 @@ class YamlTemplateVfModuleAlaCarteInstantiateStep(YamlTemplateBaseStep): if self.is_root: if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template return self.parent.yaml_template diff --git a/src/onaptests/steps/instantiate/vl_ala_carte.py b/src/onaptests/steps/instantiate/vl_ala_carte.py index 3f81228..7186c24 100644 --- a/src/onaptests/steps/instantiate/vl_ala_carte.py +++ b/src/onaptests/steps/instantiate/vl_ala_carte.py @@ -1,7 +1,7 @@ import re from typing import Iterable from uuid import uuid4 -from yaml import load +from yaml import load, SafeLoader from onapsdk.aai.business import Customer, ServiceInstance, ServiceSubscription from onapsdk.configuration import settings @@ -51,7 +51,7 @@ class YamlTemplateVlAlaCarteInstantiateStep(YamlTemplateBaseStep): if self.is_root: if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template return self.parent.yaml_template diff --git a/src/onaptests/steps/instantiate/vnf_ala_carte.py b/src/onaptests/steps/instantiate/vnf_ala_carte.py index 8dbec78..eb9896f 100644 --- a/src/onaptests/steps/instantiate/vnf_ala_carte.py +++ b/src/onaptests/steps/instantiate/vnf_ala_carte.py @@ -1,5 +1,5 @@ from uuid import uuid4 -from yaml import load +from yaml import load, SafeLoader from onapsdk.aai.cloud_infrastructure import CloudRegion, Tenant from onapsdk.aai.business import Customer, ServiceInstance, ServiceSubscription @@ -49,7 +49,7 @@ class YamlTemplateVnfAlaCarteInstantiateStep(YamlTemplateBaseStep): if self.is_root: if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template return self.parent.yaml_template diff --git a/src/onaptests/steps/loop/clamp.py b/src/onaptests/steps/loop/clamp.py index 9a705f2..c614857 100644 --- a/src/onaptests/steps/loop/clamp.py +++ b/src/onaptests/steps/loop/clamp.py @@ -6,7 +6,7 @@ # # http://www.apache.org/licenses/LICENSE-2.0 """Clamp Scenario class.""" -from yaml import load +from yaml import load, SafeLoader import random import string import time @@ -57,7 +57,7 @@ class ClampStep(YamlTemplateBaseStep): if self.is_root: if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template return self.parent.yaml_template diff --git a/src/onaptests/steps/onboard/cds.py b/src/onaptests/steps/onboard/cds.py index 7f91d56..d6645ef 100644 --- a/src/onaptests/steps/onboard/cds.py +++ b/src/onaptests/steps/onboard/cds.py @@ -214,7 +214,9 @@ class CbaPublishStep(CDSBaseStep): def __init__(self, cleanup=False) -> None: """Initialize CBA publish step.""" super().__init__(cleanup=cleanup) - self.add_step(CbaEnrichStep(cleanup=cleanup)) + """Let's skip enrichment if enriched CBA is already present""" + if Path.is_file(settings.CDS_CBA_UNENRICHED): + self.add_step(CbaEnrichStep(cleanup=cleanup)) @property def description(self) -> str: diff --git a/src/onaptests/steps/onboard/clamp.py b/src/onaptests/steps/onboard/clamp.py index 9d73a8e..72daba2 100644 --- a/src/onaptests/steps/onboard/clamp.py +++ b/src/onaptests/steps/onboard/clamp.py @@ -1,7 +1,7 @@ #!/usr/bin/python # http://www.apache.org/licenses/LICENSE-2.0 """Clamp Onboard service class.""" -from yaml import load +from yaml import load, SafeLoader from onapsdk.sdc.service import Service from onapsdk.sdc.vf import Vf @@ -49,7 +49,7 @@ class OnboardClampStep(YamlTemplateBaseStep): if self.is_root: if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template return self.parent.yaml_template diff --git a/src/onaptests/steps/onboard/service.py b/src/onaptests/steps/onboard/service.py index db1b330..6f1e69f 100644 --- a/src/onaptests/steps/onboard/service.py +++ b/src/onaptests/steps/onboard/service.py @@ -1,6 +1,6 @@ import time from typing import Any, Dict -from yaml import load +from yaml import load, SafeLoader from onapsdk.configuration import settings from onapsdk.exceptions import APIError, ResourceNotFound @@ -117,7 +117,7 @@ class YamlTemplateServiceOnboardStep(YamlTemplateBaseStep): elif self.is_root: if not self._yaml_template: with open(settings.SERVICE_YAML_TEMPLATE, "r") as yaml_template: - self._yaml_template: dict = load(yaml_template) + self._yaml_template: dict = load(yaml_template, SafeLoader) return self._yaml_template return self.parent.yaml_template diff --git a/src/onaptests/steps/onboard/vf.py b/src/onaptests/steps/onboard/vf.py index 44c3749..852cb82 100644 --- a/src/onaptests/steps/onboard/vf.py +++ b/src/onaptests/steps/onboard/vf.py @@ -1,10 +1,10 @@ from pathlib import Path -import sys import time from onapsdk.configuration import settings from onapsdk.sdc.vf import Vf from onapsdk.sdc.vsp import Vsp +from onaptests.utils.resources import get_resource_location from ..base import BaseStep, YamlTemplateBaseStep from .vsp import VspOnboardStep, YamlTemplateVspOnboardStep @@ -113,7 +113,7 @@ class YamlTemplateVfOnboardStep(YamlTemplateBaseStep): vf.create() artifact_file_path: Path = Path(vnf["vnf_artifact_file_path"]) if not artifact_file_path.exists(): - artifact_file_path = Path(sys.path[-1], artifact_file_path) + artifact_file_path = Path(get_resource_location(artifact_file_path)) vf.add_deployment_artifact( artifact_type=vnf["vnf_artifact_type"], artifact_name=vnf["vnf_artifact_name"], diff --git a/src/onaptests/steps/onboard/vsp.py b/src/onaptests/steps/onboard/vsp.py index 5462c55..f898268 100644 --- a/src/onaptests/steps/onboard/vsp.py +++ b/src/onaptests/steps/onboard/vsp.py @@ -1,7 +1,7 @@ -import sys from onapsdk.configuration import settings from onapsdk.sdc.vendor import Vendor from onapsdk.sdc.vsp import Vsp +from onaptests.utils.resources import get_resource_location from ..base import BaseStep, YamlTemplateBaseStep from .vendor import VendorOnboardStep @@ -105,8 +105,7 @@ class YamlTemplateVspOnboardStep(YamlTemplateBaseStep): vendor: Vendor = Vendor(name=settings.VENDOR_NAME) if "vnfs" in self.yaml_template: for vnf in self.yaml_template["vnfs"]: - with open( - sys.path[-1] + "/" + vnf["heat_files_to_upload"], "rb") as package: + with open(get_resource_location(vnf["heat_files_to_upload"]), "rb") as package: vsp: Vsp = Vsp(name=f"{vnf['vnf_name']}_VSP", vendor=vendor, package=package) @@ -114,8 +113,7 @@ class YamlTemplateVspOnboardStep(YamlTemplateBaseStep): elif "pnfs" in self.yaml_template: for pnf in self.yaml_template["pnfs"]: if "heat_files_to_upload" in pnf: - with open( - sys.path[-1] + "/" + pnf["heat_files_to_upload"], "rb") as package: + with open(get_resource_location(pnf["heat_files_to_upload"]), "rb") as package: vsp: Vsp = Vsp(name=f"{pnf['pnf_name']}_VSP", vendor=vendor, package=package) diff --git a/src/onaptests/steps/reports_collection.py b/src/onaptests/steps/reports_collection.py index 52a0fec..4b7f79b 100644 --- a/src/onaptests/steps/reports_collection.py +++ b/src/onaptests/steps/reports_collection.py @@ -1,10 +1,10 @@ -import sys from dataclasses import dataclass from enum import Enum from typing import List from jinja2 import Environment, FileSystemLoader, select_autoescape from onapsdk.configuration import settings from onapsdk.exceptions import SettingsError +from onaptests.utils.resources import get_resource_location class ReportStepStatus(Enum): @@ -58,8 +58,8 @@ class ReportsCollection: int: How many steps failed """ - return sum((1 for step_report in self.report if \ - step_report.step_execution_status == ReportStepStatus.FAIL)) + return sum((1 for step_report in self.report if + step_report.step_execution_status == ReportStepStatus.FAIL)) def generate_report(self) -> None: usecase = settings.SERVICE_NAME @@ -75,7 +75,7 @@ class ReportsCollection: jinja_env = Environment( autoescape=select_autoescape(['html']), - loader=FileSystemLoader(sys.path[-1] + '/onaptests/templates/reporting')) + loader=FileSystemLoader(get_resource_location('templates/reporting'))) jinja_env.get_template('reporting.html.j2').stream( report=self, diff --git a/src/onaptests/steps/wrapper/helm_charts.py b/src/onaptests/steps/wrapper/helm_charts.py index 4482683..b8a6b21 100644 --- a/src/onaptests/steps/wrapper/helm_charts.py +++ b/src/onaptests/steps/wrapper/helm_charts.py @@ -3,7 +3,7 @@ import yaml from avionix import ChartBuilder, ChartDependency, ChartInfo from avionix.errors import HelmError from onaptests.steps.base import BaseStep -from onaptests.utils.simulators import get_local_dir +from onaptests.utils.resources import get_local_dir from onaptests.utils.exceptions import ( EnvironmentPreparationException, EnvironmentCleanupException) diff --git a/src/onaptests/templates/artifacts/basic_cnf_cba_enriched.zip b/src/onaptests/templates/artifacts/basic_cnf_cba_enriched.zip new file mode 100644 index 0000000000000000000000000000000000000000..825160c3bfe626e48e0fd0086c0ff34569693bb3 GIT binary patch literal 60824 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 u%}jhj`|Q8q;N+!=<^7Qfc-pJ#7LO1{W{@ literal 0 HcmV?d00001 diff --git a/src/onaptests/templates/heat-files/basic_cnf_macro/basic_cnf_macro.zip b/src/onaptests/templates/heat-files/basic_cnf_macro/basic_cnf_macro.zip new file mode 100644 index 0000000000000000000000000000000000000000..e9f5b4cc4f8a08b58e23df37a0778a5722719e3b GIT binary patch literal 20627 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 G0R9CxSOVz) literal 0 HcmV?d00001 diff --git a/src/onaptests/templates/vnf-services/basic_clamp-service.yaml b/src/onaptests/templates/vnf-services/basic_clamp-service.yaml index f5fe653..f3ea53b 100644 --- a/src/onaptests/templates/vnf-services/basic_clamp-service.yaml +++ b/src/onaptests/templates/vnf-services/basic_clamp-service.yaml @@ -2,7 +2,7 @@ basicclamp: vnfs: - vnf_name: basicclamp - heat_files_to_upload: onaptests/templates/heat-files/ubuntu18/ubuntu18agent.zip + heat_files_to_upload: templates/heat-files/ubuntu18/ubuntu18agent.zip vnf_parameters: [ {"name": "ubuntu18_image_name", "value": "ubuntu-agent" diff --git a/src/onaptests/templates/vnf-services/basic_cnf-service.yaml b/src/onaptests/templates/vnf-services/basic_cnf-service.yaml index c3c701f..047a244 100644 --- a/src/onaptests/templates/vnf-services/basic_cnf-service.yaml +++ b/src/onaptests/templates/vnf-services/basic_cnf-service.yaml @@ -5,7 +5,7 @@ basic_cnf: subscription_type: "basic_cnf" vnfs: - vnf_name: basic_cnf - heat_files_to_upload: onaptests/templates/heat-files/basic_cnf/basic_cnf.zip + heat_files_to_upload: templates/heat-files/basic_cnf/basic_cnf.zip vnf_parameters: [ {"name": "dummy_name_0", "value": "dummy_name" diff --git a/src/onaptests/templates/vnf-services/basic_cnf_macro-service.yaml b/src/onaptests/templates/vnf-services/basic_cnf_macro-service.yaml new file mode 100644 index 0000000..3660e2b --- /dev/null +++ b/src/onaptests/templates/vnf-services/basic_cnf_macro-service.yaml @@ -0,0 +1,68 @@ +--- +basic_cnf_macro: + tosca_file_from_SDC: service-basic_cnf_macro-template + version: "1.0" + subscription_type: "basic_cnf_macro" + vnfs: + - vnf_name: basic_cnf_macro + properties: + controller_actor: "CDS" + skip_post_instantiation_configuration: False + sdnc_artifact_name: "vnf" + sdnc_model_version: "1.0.0" + sdnc_model_name: "APACHE" + vnf_artifact_type: "CONTROLLER_BLUEPRINT_ARCHIVE" + vnf_artifact_name: "basic_cnf_cba_enriched.zip" + vnf_artifact_label: "vnfcba" + vnf_artifact_file_path: templates/artifacts/basic_cnf_cba_enriched.zip + heat_files_to_upload: templates/heat-files/basic_cnf_macro/basic_cnf_macro.zip + vnf_parameters: [ + { + "name": "k8s-rb-profile-namespace", + "value": "apache" + }, + { + "name": "k8s-rb-profile-k8s-version", + "value": "1.19.0" + } + ] + vf_module_parameters: + - vf_module_name: helm_apache + parameters: [ + { + "name": "vf_module_label", + "value": "helm_apache" + }, + { + "name": "k8s-rb-profile-name", + "value": "node-port-profile" + }, + { + "name": "k8s-rb-profile-source", + "value": "node-port-profile" + }, + { + "name": "k8s-rb-profile-namespace", + "value": "apache" + }, + { + "name": "k8s-rb-instance-release-name", + "value": "rel-1-apache" + }, + { + "name": "k8s-rb-config-template-name", + "value": "replica-count-template" + }, + { + "name": "k8s-rb-config-template-source", + "value": "deployment-config" + }, + { + "name": "k8s-rb-config-name", + "value": "replica-count-change" + }, + { + "name": "k8s-rb-config-value-source", + "value": "custom-values" + } + ] diff --git a/src/onaptests/templates/vnf-services/basic_onboard-service.yaml.j2 b/src/onaptests/templates/vnf-services/basic_onboard-service.yaml.j2 index db84783..8cc4fe5 100644 --- a/src/onaptests/templates/vnf-services/basic_onboard-service.yaml.j2 +++ b/src/onaptests/templates/vnf-services/basic_onboard-service.yaml.j2 @@ -2,7 +2,7 @@ {{ service_name }}: vnfs: - vnf_name: {{ service_name }} - heat_files_to_upload: onaptests/templates/heat-files/ubuntu18/ubuntu18agent.zip + heat_files_to_upload: templates/heat-files/ubuntu18/ubuntu18agent.zip vnf_parameters: [ {"name": "ubuntu18_image_name", "value": "ubuntu-agent" diff --git a/src/onaptests/templates/vnf-services/basic_vm-service.yaml b/src/onaptests/templates/vnf-services/basic_vm-service.yaml index 227ec48..eb4522a 100644 --- a/src/onaptests/templates/vnf-services/basic_vm-service.yaml +++ b/src/onaptests/templates/vnf-services/basic_vm-service.yaml @@ -2,7 +2,7 @@ basic_vm: vnfs: - vnf_name: basic_vm - heat_files_to_upload: onaptests/templates/heat-files/ubuntu20/ubuntu20agent.zip + heat_files_to_upload: templates/heat-files/ubuntu20/ubuntu20agent.zip vnf_parameters: [ {"name": "ubuntu20_image_name", "value": "ubuntu-20.04" diff --git a/src/onaptests/templates/vnf-services/basic_vm_macro-service.yaml b/src/onaptests/templates/vnf-services/basic_vm_macro-service.yaml index 00f66d5..2a616a5 100644 --- a/src/onaptests/templates/vnf-services/basic_vm_macro-service.yaml +++ b/src/onaptests/templates/vnf-services/basic_vm_macro-service.yaml @@ -13,7 +13,7 @@ basic_vm_macro: vnf_artifact_name: "BASIC_VM_enriched.zip" vnf_artifact_label: "vnfcds" vnf_artifact_file_path: "/tmp/BASIC_VM_enriched.zip" - heat_files_to_upload: onaptests/templates/heat-files/ubuntu20/ubuntu20agent.zip + heat_files_to_upload: templates/heat-files/ubuntu20/ubuntu20agent.zip vf_module_parameters: - vf_module_name: base_ubuntu20 parameters: [ diff --git a/src/onaptests/templates/vnf-services/basic_vm_macro_stability-service.yaml b/src/onaptests/templates/vnf-services/basic_vm_macro_stability-service.yaml index 62170bd..d9454c3 100644 --- a/src/onaptests/templates/vnf-services/basic_vm_macro_stability-service.yaml +++ b/src/onaptests/templates/vnf-services/basic_vm_macro_stability-service.yaml @@ -12,8 +12,8 @@ basic_vm_macro: vnf_artifact_type: "CONTROLLER_BLUEPRINT_ARCHIVE" vnf_artifact_name: "BASIC_VM_enriched.zip" vnf_artifact_label: "vnfcds" - vnf_artifact_file_path: onaptests/templates/artifacts/basic_vm_cba_enriched.zip - heat_files_to_upload: onaptests/templates/heat-files/ubuntu20/ubuntu20agent.zip + vnf_artifact_file_path: templates/artifacts/basic_vm_cba_enriched.zip + heat_files_to_upload: templates/heat-files/ubuntu20/ubuntu20agent.zip vf_module_parameters: - vf_module_name: base_ubuntu20 parameters: [ diff --git a/src/onaptests/templates/vnf-services/clearwater-ims-service.yaml b/src/onaptests/templates/vnf-services/clearwater-ims-service.yaml index d720b2c..49824c1 100644 --- a/src/onaptests/templates/vnf-services/clearwater-ims-service.yaml +++ b/src/onaptests/templates/vnf-services/clearwater-ims-service.yaml @@ -2,7 +2,7 @@ clearwater_ims: vnfs: - vnf_name: clearwater_ims_vnf - heat_files_to_upload: onaptests/templates/heat-files/clearwater_ims/clearwater_ims.zip + heat_files_to_upload: templates/heat-files/clearwater_ims/clearwater_ims.zip vnf_parameters: [ {"name": "public_net_id", "value": "FILL ME"}, diff --git a/src/onaptests/templates/vnf-services/multi-vnf-ubuntu-model.yaml.j2 b/src/onaptests/templates/vnf-services/multi-vnf-ubuntu-model.yaml.j2 index 96037c9..7a701e5 100644 --- a/src/onaptests/templates/vnf-services/multi-vnf-ubuntu-model.yaml.j2 +++ b/src/onaptests/templates/vnf-services/multi-vnf-ubuntu-model.yaml.j2 @@ -13,4 +13,4 @@ vnf_artifact_name: "UBUNTUVNF_enriched.zip" vnf_artifact_label: "UbuntuVNF" vnf_artifact_file_path: "/tmp/UBUNTUVNF_enriched.zip" - heat_files_to_upload: onaptests/templates/heat-files/nso_ubuntu/nso_ubuntu.zip + heat_files_to_upload: templates/heat-files/nso_ubuntu/nso_ubuntu.zip diff --git a/src/onaptests/templates/vnf-services/pnf-service.yaml b/src/onaptests/templates/vnf-services/pnf-service.yaml index 2dcdfbb..e9ca513 100644 --- a/src/onaptests/templates/vnf-services/pnf-service.yaml +++ b/src/onaptests/templates/vnf-services/pnf-service.yaml @@ -6,7 +6,7 @@ test_pnf_macro: instantiation_type: "Macro" pnfs: - pnf_name: "test-pnf" - heat_files_to_upload: onaptests/templates/artifacts/pNF.csar + heat_files_to_upload: templates/artifacts/pNF.csar pnf_artifact_type: "CONTROLLER_BLUEPRINT_ARCHIVE" pnf_artifact_name: "CBA_enriched.zip" pnf_artifact_label: "cbapnf" diff --git a/src/onaptests/utils/simulators.py b/src/onaptests/utils/resources.py similarity index 67% rename from src/onaptests/utils/simulators.py rename to src/onaptests/utils/resources.py index 08acdbd..46c6c6e 100644 --- a/src/onaptests/utils/simulators.py +++ b/src/onaptests/utils/resources.py @@ -1,5 +1,13 @@ """Standard functions for the simulator wrapper.""" +import os from importlib.resources import path +import onaptests + + +def get_resource_location(relative_path: str): + return os.path.join(os.path.dirname(os.path.realpath(onaptests.__file__)), + relative_path) + def get_local_dir(): """Get the default path for helm charts. diff --git a/tox.ini b/tox.ini index ee2b4c0..50e841e 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,8 @@ whitelist_externals = git bash deps = + pyyaml == 3.13 + bandit == 1.3 coala-bears nodeenv -- 2.16.6