From ca74c6ae7ad7dfd03f547fcd706bdfcdde1b20b4 Mon Sep 17 00:00:00 2001 From: Michal Jagiello Date: Mon, 15 Feb 2021 21:33:17 +0000 Subject: [TEST] Collect steps cleanup reports Collect reports of steps cleanup and present them in report Issue-ID: TEST-305 Signed-off-by: Michal Jagiello Change-Id: Ie288c85a381c6c53e7ffeb441f07e474a135c42d --- src/onaptests/steps/base.py | 92 ++++++++++++++++++---- .../steps/cloud/k8s_connectivity_info_create.py | 1 + .../steps/instantiate/k8s_profile_create.py | 1 + src/onaptests/steps/instantiate/msb_k8s.py | 1 + .../steps/instantiate/service_ala_carte.py | 2 +- src/onaptests/steps/instantiate/service_macro.py | 2 +- .../steps/instantiate/vf_module_ala_carte.py | 2 +- src/onaptests/steps/instantiate/vl_ala_carte.py | 1 + src/onaptests/steps/instantiate/vnf_ala_carte.py | 1 + src/onaptests/steps/loop/clamp.py | 1 + src/onaptests/steps/onboard/cds.py | 1 + src/onaptests/steps/reports_collection.py | 2 + .../templates/reporting/reporting.html.j2 | 2 +- src/onaptests/utils/exceptions.py | 3 + 14 files changed, 91 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/onaptests/steps/base.py b/src/onaptests/steps/base.py index 97924bd..8c67e5d 100644 --- a/src/onaptests/steps/base.py +++ b/src/onaptests/steps/base.py @@ -1,14 +1,17 @@ +import functools +import itertools import logging import logging.config import time from abc import ABC, abstractmethod -from typing import List +from typing import Iterator, List from onapsdk.aai.business import Customer from onapsdk.configuration import settings -from onapsdk.exceptions import SettingsError +from onapsdk.exceptions import SDKException, SettingsError -from .reports_collection import Report, ReportsCollection, ReportStepStatus +from onaptests.steps.reports_collection import Report, ReportsCollection, ReportStepStatus +from onaptests.utils.exceptions import OnapTestException, SubstepExecutionException class BaseStep(ABC): @@ -41,7 +44,10 @@ class BaseStep(ABC): self._cleanup: bool = cleanup self._parent: "BaseStep" = None self._reports_collection: ReportsCollection = None - self._start_time: float = None + self._start_execution_time: float = None + self._start_cleanup_time: float = None + self._execution_report: ReportStepStatus = None + self._cleanup_report: ReportStepStatus = None def add_step(self, step: "BaseStep") -> None: """Add substep. @@ -88,8 +94,41 @@ class BaseStep(ABC): return self.parent.reports_collection if not self._reports_collection: self._reports_collection = ReportsCollection() + for step_report in itertools.chain(self.execution_reports, self.cleanup_reports): + self._reports_collection.put(step_report) return self._reports_collection + @property + def execution_reports(self) -> Iterator[ReportsCollection]: + """Execution reports generator. + + Steps tree postorder traversal + + Yields: + Iterator[ReportsCollection]: Step execution report + + """ + for step in self._steps: + yield from step.execution_reports + if self._execution_report: + yield self._execution_report + + @property + def cleanup_reports(self) -> Iterator[ReportsCollection]: + """Cleanup reports generator. + + Steps tree preorder traversal + + Yields: + Iterator[ReportsCollection]: Step cleanup report + + """ + if self._cleanup: + if self._cleanup_report: + yield self._cleanup_report + for step in self._steps: + yield from step.cleanup_reports + @property def name(self) -> str: """Step name.""" @@ -121,27 +160,40 @@ class BaseStep(ABC): """ @classmethod - def store_state(cls, fun): + def store_state(cls, fun=None, *, cleanup=False): + if fun is None: + return functools.partial(cls.store_state, cleanup=cleanup) + @functools.wraps(fun) def wrapper(self, *args, **kwargs): try: + if cleanup: + self._start_cleanup_time = time.time() ret = fun(self, *args, **kwargs) execution_status: ReportStepStatus = ReportStepStatus.PASS return ret - except Exception: + except SubstepExecutionException: + execution_status: ReportStepStatus = ReportStepStatus.PASS if cleanup else ReportStepStatus.NOT_EXECUTED + raise + except (OnapTestException, SDKException): execution_status: ReportStepStatus = ReportStepStatus.FAIL raise finally: - if not self._start_time: - self._logger.error("No execution start time saved for %s step. Fix it by call `super.execute()` " - "in step class `execute()` method definition") - self._start_time = time.time() - self.reports_collection.put( - Report( + if cleanup: + 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: + if not self._start_execution_time: + self._logger.error("No execution start time saved for %s step. Fix it by call `super.execute()` " + "in step class `execute()` method definition", self.name) + self._start_execution_time = time.time() + self._execution_report = Report( step_description=f"[{self.component}] {self.name}: {self.description}", step_execution_status=execution_status, - step_execution_duration=time.time() - self._start_time + step_execution_duration=time.time() - self._start_execution_time ) - ) return wrapper def execute(self) -> None: @@ -152,8 +204,11 @@ class BaseStep(ABC): """ for step in self._steps: - step.execute() - self._start_time = time.time() + try: + step.execute() + except (OnapTestException, SDKException) as substep_err: + raise SubstepExecutionException from substep_err + self._start_execution_time = time.time() def cleanup(self) -> None: """Step's cleanup. @@ -163,7 +218,10 @@ class BaseStep(ABC): """ if self._cleanup: for step in self._steps: - step.cleanup() + try: + step.cleanup() + except (OnapTestException, SDKException) as substep_err: + raise SubstepExecutionException from substep_err @classmethod def set_proxy(cls, sock_http): diff --git a/src/onaptests/steps/cloud/k8s_connectivity_info_create.py b/src/onaptests/steps/cloud/k8s_connectivity_info_create.py index 2855be7..6d0faf6 100644 --- a/src/onaptests/steps/cloud/k8s_connectivity_info_create.py +++ b/src/onaptests/steps/cloud/k8s_connectivity_info_create.py @@ -38,6 +38,7 @@ class K8SConnectivityInfoStep(BaseStep): settings.CLOUD_REGION_CLOUD_OWNER, open(settings.K8S_CONFIG, 'rb').read()) + @BaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Cleanup K8S Connectivity information.""" self._logger.info("Clean the k8s connectivity information") diff --git a/src/onaptests/steps/instantiate/k8s_profile_create.py b/src/onaptests/steps/instantiate/k8s_profile_create.py index c2692c8..d555d46 100644 --- a/src/onaptests/steps/instantiate/k8s_profile_create.py +++ b/src/onaptests/steps/instantiate/k8s_profile_create.py @@ -151,6 +151,7 @@ class K8SProfileStep(BaseStep): ####### Upload artifact for created profile ############################## profile.upload_artifact(open(settings.K8S_PROFILE_ARTIFACT_PATH, 'rb').read()) + @BaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Cleanup K8S profiles. """ diff --git a/src/onaptests/steps/instantiate/msb_k8s.py b/src/onaptests/steps/instantiate/msb_k8s.py index eac8a75..e6186f5 100644 --- a/src/onaptests/steps/instantiate/msb_k8s.py +++ b/src/onaptests/steps/instantiate/msb_k8s.py @@ -38,6 +38,7 @@ class CreateInstanceStep(BaseStep): rb_name=settings.PNF_RB_NAME, rb_version=settings.PNF_RB_VERSION) + @BaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Delete instance.""" if self.instance: diff --git a/src/onaptests/steps/instantiate/service_ala_carte.py b/src/onaptests/steps/instantiate/service_ala_carte.py index 6000e73..eb3c882 100644 --- a/src/onaptests/steps/instantiate/service_ala_carte.py +++ b/src/onaptests/steps/instantiate/service_ala_carte.py @@ -233,7 +233,7 @@ class YamlTemplateServiceAlaCarteInstantiateStep(YamlTemplateBaseStep): service_subscription: ServiceSubscription = customer.get_service_subscription_by_service_type(self.service_name) self._service_instance: ServiceInstance = service_subscription.get_service_instance_by_name(self.service_instance_name) - + @YamlTemplateBaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Cleanup Service. diff --git a/src/onaptests/steps/instantiate/service_macro.py b/src/onaptests/steps/instantiate/service_macro.py index 04c3931..526eecc 100644 --- a/src/onaptests/steps/instantiate/service_macro.py +++ b/src/onaptests/steps/instantiate/service_macro.py @@ -186,7 +186,7 @@ class YamlTemplateServiceMacroInstantiateStep(YamlTemplateBaseStep): service_subscription: ServiceSubscription = customer.get_service_subscription_by_service_type(self.service_name) self._service_instance: ServiceInstance = service_subscription.get_service_instance_by_name(self.service_instance_name) - + @YamlTemplateBaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Cleanup Service. diff --git a/src/onaptests/steps/instantiate/vf_module_ala_carte.py b/src/onaptests/steps/instantiate/vf_module_ala_carte.py index 115966a..2c1834e 100644 --- a/src/onaptests/steps/instantiate/vf_module_ala_carte.py +++ b/src/onaptests/steps/instantiate/vf_module_ala_carte.py @@ -148,7 +148,7 @@ class YamlTemplateVfModuleAlaCarteInstantiateStep(YamlTemplateBaseStep): if vf_module_instantiation.failed: raise onap_test_exceptions.VfModuleInstantiateException - + @YamlTemplateBaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Cleanup Vf module. diff --git a/src/onaptests/steps/instantiate/vl_ala_carte.py b/src/onaptests/steps/instantiate/vl_ala_carte.py index f2815a4..f9ac560 100644 --- a/src/onaptests/steps/instantiate/vl_ala_carte.py +++ b/src/onaptests/steps/instantiate/vl_ala_carte.py @@ -146,6 +146,7 @@ class YamlTemplateVlAlaCarteInstantiateStep(YamlTemplateBaseStep): if net_instantiation.failed: raise onap_test_exceptions.NetworkInstantiateException + @YamlTemplateBaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Cleanup VL. diff --git a/src/onaptests/steps/instantiate/vnf_ala_carte.py b/src/onaptests/steps/instantiate/vnf_ala_carte.py index 6b9c4a4..64ea090 100644 --- a/src/onaptests/steps/instantiate/vnf_ala_carte.py +++ b/src/onaptests/steps/instantiate/vnf_ala_carte.py @@ -123,6 +123,7 @@ class YamlTemplateVnfAlaCarteInstantiateStep(YamlTemplateBaseStep): if vnf_instantiation.failed: raise onap_test_exceptions.VnfInstantiateException + @YamlTemplateBaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Cleanup VNF. diff --git a/src/onaptests/steps/loop/clamp.py b/src/onaptests/steps/loop/clamp.py index b46e723..9ae5a5f 100644 --- a/src/onaptests/steps/loop/clamp.py +++ b/src/onaptests/steps/loop/clamp.py @@ -148,6 +148,7 @@ class ClampStep(YamlTemplateBaseStep): loop_name=loop_name, operational_policies=operational_policies) + @YamlTemplateBaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Cleanup Service. diff --git a/src/onaptests/steps/onboard/cds.py b/src/onaptests/steps/onboard/cds.py index f7fc77a..6ee0ae1 100644 --- a/src/onaptests/steps/onboard/cds.py +++ b/src/onaptests/steps/onboard/cds.py @@ -124,6 +124,7 @@ class CbaEnrichStep(CDSBaseStep): blueprint.enrich() blueprint.save(settings.CDS_CBA_ENRICHED) + @BaseStep.store_state(cleanup=True) def cleanup(self) -> None: """Cleanup enrichment step. diff --git a/src/onaptests/steps/reports_collection.py b/src/onaptests/steps/reports_collection.py index 34b28af..52a0fec 100644 --- a/src/onaptests/steps/reports_collection.py +++ b/src/onaptests/steps/reports_collection.py @@ -6,10 +6,12 @@ from jinja2 import Environment, FileSystemLoader, select_autoescape from onapsdk.configuration import settings from onapsdk.exceptions import SettingsError + class ReportStepStatus(Enum): """Enum which stores steps execution statuses.""" PASS = "PASS" FAIL = "FAIL" + NOT_EXECUTED = "NOT EXECUTED" @dataclass diff --git a/src/onaptests/templates/reporting/reporting.html.j2 b/src/onaptests/templates/reporting/reporting.html.j2 index 05c00b7..246f362 100644 --- a/src/onaptests/templates/reporting/reporting.html.j2 +++ b/src/onaptests/templates/reporting/reporting.html.j2 @@ -28,7 +28,7 @@ {% for step_report in report.report %} - + {{ step_report.step_description }} diff --git a/src/onaptests/utils/exceptions.py b/src/onaptests/utils/exceptions.py index ea9f5ae..e453d67 100644 --- a/src/onaptests/utils/exceptions.py +++ b/src/onaptests/utils/exceptions.py @@ -71,3 +71,6 @@ class ProfileCleanupException(OnapTestException): class EnvironmentPreparationException(OnapTestException): """Test environment preparation exception.""" error_message="Test can't be run properly due to preparation error" + +class SubstepExecutionException(OnapTestException): + """Exception raised if substep execution fails.""" -- cgit 1.2.3-korg