iact3/testing/base.py (126 lines of code) (raw):

import abc import logging import uuid from pathlib import Path from typing import Any, Type, TypeVar, List from iact3.config import BaseConfig, PROJECT, REGIONS, TEMPLATE_CONFIG, TestConfig, IAC_NAME, \ DEFAULT_PROJECT_ROOT, OssConfig, Auth, TEMPLATE_LOCATION, DEFAULT_CONFIG_FILE, DEFAULT_OUTPUT_DIRECTORY from iact3.exceptions import Iact3Exception from iact3.plugin.oss import OssPlugin from iact3.report.generate_reports import ReportBuilder from iact3.stack import Stacker from iact3.termial_print import TerminalPrinter LOG = logging.getLogger(__name__) T = TypeVar("T", bound="Test") class Base(metaclass=abc.ABCMeta): def __init__(self, project_name: str, configs: List[TestConfig], no_delete: bool = False, keep_failed: bool = False, dont_wait_for_delete: bool = False, rerun_failed: bool = False, oss_config: OssConfig = None, auth: Auth = None ): self.project_name = project_name self.configs = configs self.passed: bool = False self.result: Any = None self.printer = TerminalPrinter() self.stacker: Stacker = None self.uid = uuid.uuid4() self.no_delete = no_delete self.keep_failed = keep_failed self.dont_wait_for_delete = dont_wait_for_delete self.rerun_failed = rerun_failed self.oss_config = oss_config self.auth = auth async def __aenter__(self) -> Any: LOG.info(f'test {self.uid} start running.') try: await self.run() except BaseException as ex: await self.clean_up() raise ex return self.result async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: await self.clean_up() @classmethod async def from_file(cls: Type[T], template: str, project_config_file: str, regions: str, project_path: str = None, no_delete: bool = False, keep_failed: bool = False, dont_wait_for_delete: bool = False, rerun_failed: bool = False, test_names: str = None ) -> T: args = {} if regions: args[REGIONS] = regions.split(',') if project_path: project_root = Path(project_path).expanduser().resolve() if template: template = template.lstrip('/') template_path = project_root / template args[TEMPLATE_CONFIG] = {TEMPLATE_LOCATION: str(template_path)} else: args[TEMPLATE_CONFIG] = {TEMPLATE_LOCATION: str(project_root)} else: project_path = DEFAULT_PROJECT_ROOT if template: args[TEMPLATE_CONFIG] = {TEMPLATE_LOCATION: template} base_config = BaseConfig.create( project_config_file=project_config_file or DEFAULT_CONFIG_FILE, args={PROJECT: args}, project_path=project_path ) project_name = base_config.project.name if not project_name: raise Iact3Exception('project name should be specified') configs = await base_config.get_all_configs(test_names) return cls(project_name, configs, no_delete=no_delete, keep_failed=keep_failed, dont_wait_for_delete=dont_wait_for_delete, rerun_failed=rerun_failed, oss_config=base_config.project.oss_config, auth=base_config.general.auth) async def report(self, output_directory, project_path=None, log_format=None): project_root = Path(project_path).expanduser().resolve() if project_path else DEFAULT_PROJECT_ROOT output_directory = output_directory or DEFAULT_OUTPUT_DIRECTORY report_path = project_root / output_directory report_path.mkdir(exist_ok=True) reporter = ReportBuilder(self.stacker, report_path) file_names = await reporter.create_logs(log_format) index = await reporter.generate_report() self._upload_to_oss(report_path, index, file_names) def _upload_to_oss(self, report_path: Path, index: str, file_names: list): bucket = self.oss_config.bucket_name region = self.oss_config.bucket_region if bucket and region: LOG.info(f'starting upload reports to oss bucket {bucket} ' f'which is in {region} region') oss_prefix = self.oss_config.object_prefix or f'{report_path.name}-{self.uid}' oss_prefix = f'{IAC_NAME}/{oss_prefix}' oss_plugin = OssPlugin( region_id=region, bucket_name=bucket, credential=self.auth.credential) for file_name in file_names: oss_plugin.put_local_file(f'{oss_prefix}/{file_name}', report_path / file_name) callback_config = self.oss_config.callback_params if callback_config.callback_url: callback_params = { 'callbackUrl': callback_config.callback_url, 'callbackHost': callback_config.callback_host, 'callbackBody': callback_config.callback_body, 'callbackBodyType': callback_config.callback_body_type, } callback_var_params = callback_config.callback_var_params oss_plugin.put_object_with_string( f'{oss_prefix}/index.html', index, callback_params, callback_var_params) else: oss_plugin.put_object_with_string(f'{oss_prefix}/index.html', index) @abc.abstractmethod async def run(self): raise NotImplementedError @abc.abstractmethod async def clean_up(self): raise NotImplementedError