diff --git a/tdp/cli/commands/browse.py b/tdp/cli/commands/browse.py index a54a44b7..9e4765b3 100644 --- a/tdp/cli/commands/browse.py +++ b/tdp/cli/commands/browse.py @@ -8,12 +8,12 @@ from tdp.cli.queries import ( get_deployment, get_deployments, - get_operation_log, + get_operation_records, get_planned_deployment, ) from tdp.cli.session import get_session from tdp.cli.utils import database_dsn, print_deployment, print_object, print_table -from tdp.core.models import DeploymentModel, OperationLog +from tdp.core.models import DeploymentModel, OperationModel @click.command(short_help="Browse deployments") @@ -61,7 +61,7 @@ def browse( # Print a specific operation if deployment_id and operation: - _print_operations(get_operation_log(session, deployment_id, operation)) + _print_operations(get_operation_records(session, deployment_id, operation)) return # Print a specific deployment @@ -101,7 +101,7 @@ def _print_deployment(deployment: DeploymentModel) -> None: print_deployment(deployment, filter_out=["logs"]) -def _print_operations(operations: list[OperationLog]) -> None: +def _print_operations(operations: list[OperationModel]) -> None: """Print a list of operations in a human readable format. Args: @@ -111,7 +111,7 @@ def _print_operations(operations: list[OperationLog]) -> None: click.secho("Operation(s) details", bold=True) for operation in operations: click.echo(print_object(operation.to_dict())) - # Print operation logs + # Print operation records if operation.logs: - click.secho("\nOperation logs", bold=True) + click.secho("\nOperations", bold=True) click.echo(str(operation.logs, "utf-8")) diff --git a/tdp/cli/queries.py b/tdp/cli/queries.py index 9d5db2f9..79249b00 100644 --- a/tdp/cli/queries.py +++ b/tdp/cli/queries.py @@ -10,7 +10,7 @@ from tdp.core.models import ( DeploymentModel, - OperationLog, + OperationModel, SCHStatusLogModel, ) @@ -447,10 +447,10 @@ def get_planned_deployment(session: Session) -> Optional[DeploymentModel]: return session.query(DeploymentModel).filter_by(status="PLANNED").one_or_none() -def get_operation_log( +def get_operation_records( session: Session, deployment_id: int, operation_name: str -) -> list[OperationLog]: - """Get an operation log. +) -> list[OperationModel]: + """Get an operation records. Args: session: The database session. @@ -458,14 +458,14 @@ def get_operation_log( operation_name: The operation name. Returns: - List of matching operation logs. + List of matching operation records. Raises: NoResultFound: If the operation does not exist. """ try: return ( - session.query(OperationLog) + session.query(OperationModel) .filter_by(deployment_id=deployment_id, operation=operation_name) .all() ) diff --git a/tdp/core/deployment/deployment_iterator.py b/tdp/core/deployment/deployment_iterator.py index fa0eb8e2..cb271cc7 100644 --- a/tdp/core/deployment/deployment_iterator.py +++ b/tdp/core/deployment/deployment_iterator.py @@ -15,7 +15,7 @@ DeploymentModel, DeploymentStateEnum, NothingToReconfigureError, - OperationLog, + OperationModel, OperationStateEnum, SCHStatusLogModel, SCHStatusLogSourceEnum, @@ -38,9 +38,9 @@ def _group_hosts_by_operation( Example: >>> _group_hosts_by_operation(DeploymentModel( ... operations=[ - ... OperationLog(operation="s_c_install", host="host1"), - ... OperationLog(operation="s_c_config", host="host1"), - ... OperationLog(operation="s_c_config", host="host2"), + ... OperationModel(operation="s_c_install", host="host1"), + ... OperationModel(operation="s_c_config", host="host1"), + ... OperationModel(operation="s_c_config", host="host2"), ... ] ... )) {'s_c_install': {'host1'}, 's_c_config': {'host1', 'host2'}} @@ -49,9 +49,9 @@ def _group_hosts_by_operation( return None operation_to_hosts_set = OrderedDict() - for operation_log in deployment.operations: - operation_to_hosts_set.setdefault(operation_log.operation, set()).add( - operation_log.host + for operation in deployment.operations: + operation_to_hosts_set.setdefault(operation.operation, set()).add( + operation.host ) return operation_to_hosts_set @@ -68,7 +68,7 @@ def __init__( deployment: DeploymentModel, *, collections: Collections, - run_method: Callable[[OperationLog], None], + run_method: Callable[[OperationModel], None], cluster_variables: ClusterVariables, cluster_status: ClusterStatus, force_stale_update: bool, @@ -102,25 +102,25 @@ def __init__( def __next__(self) -> Optional[list[SCHStatusLogModel]]: try: while True: - operation_log: OperationLog = next(self._iter) + operation_rec: OperationModel = next(self._iter) # Return early if deployment failed if self.deployment.status == DeploymentStateEnum.FAILURE: - operation_log.state = OperationStateEnum.HELD + operation_rec.state = OperationStateEnum.HELD return # Retrieve operation to access parsed attributes and playbook - operation = self._collections.get_operation(operation_log.operation) + operation = self._collections.get_operation(operation_rec.operation) # Run the operation if operation.noop: # A noop operation is always successful - operation_log.state = OperationStateEnum.SUCCESS + operation_rec.state = OperationStateEnum.SUCCESS else: - self._run_operation(operation_log) + self._run_operation(operation_rec) # Set deployment status to failure if the operation failed - if operation_log.state != OperationStateEnum.SUCCESS: + if operation_rec.state != OperationStateEnum.SUCCESS: self.deployment.status = DeploymentStateEnum.FAILURE # Return early as status is not updated return @@ -153,13 +153,13 @@ def __next__(self) -> Optional[list[SCHStatusLogModel]]: first_reconfigure_operation = None can_update_stale = self.force_stale_update or ( - operation_log.operation == first_reconfigure_operation + operation_rec.operation == first_reconfigure_operation ) # Log a warning if the operation affect a stale SCH which is not the first reconfigure operation (if any) if not can_update_stale: logger.warning( - f"can't update stale {sc_name} with {operation_log.operation}\n" + f"can't update stale {sc_name} with {operation_rec.operation}\n" + "first operation is {first_reconfigure_operation}" ) else: @@ -168,7 +168,7 @@ def __next__(self) -> Optional[list[SCHStatusLogModel]]: # fmt: off hosts = ( [None] if operation.noop # A noop operation doesn't have any host - else [operation_log.host] if operation_log.host # Only one operation is launched on a single host + else [operation_rec.host] if operation_rec.host # Only one operation is launched on a single host else operation.host_names # Host is not specified, hence the operation is launched on all host ) # fmt: on @@ -193,16 +193,16 @@ def __next__(self) -> Optional[list[SCHStatusLogModel]]: # Update the reconfigure_operations dict if self._reconfigure_operations: hosts = self._reconfigure_operations.get( - operation_log.operation, set() + operation_rec.operation, set() ) # If host is defined and needed to be reconfigured, # remove it from the reconfigure_operations dict - if operation_log.host and operation_log.host in hosts: - hosts.remove(operation_log.host) + if operation_rec.host and operation_rec.host in hosts: + hosts.remove(operation_rec.host) # If no host is defined, or no host is left, # remove the entire operation from the reconfigure_operations dict - if not operation_log.host or len(hosts) == 0: - self._reconfigure_operations.pop(operation_log.operation, None) + if not operation_rec.host or len(hosts) == 0: + self._reconfigure_operations.pop(operation_rec.operation, None) return sch_status_logs # StopIteration is a "normal" exception raised when the iteration has stopped diff --git a/tdp/core/deployment/deployment_runner.py b/tdp/core/deployment/deployment_runner.py index 4ec6efbb..ed2f308e 100644 --- a/tdp/core/deployment/deployment_runner.py +++ b/tdp/core/deployment/deployment_runner.py @@ -15,7 +15,7 @@ from tdp.core.cluster_status import ClusterStatus from tdp.core.collections import Collections from tdp.core.deployment.executor import Executor - from tdp.core.models import DeploymentModel, OperationLog + from tdp.core.models import DeploymentModel, OperationModel logger = logging.getLogger(__name__) @@ -43,26 +43,26 @@ def __init__( self._cluster_variables = cluster_variables self._cluster_status = cluster_status - def _run_operation(self, operation_log: OperationLog) -> None: + def _run_operation(self, operation_rec: OperationModel) -> None: """Run operation. Args: - operation_log: Operation to run, modified in place with the result. + operation_rec: Operation record to run, modified in place with the result. """ - operation_log.start_time = datetime.utcnow() + operation_rec.start_time = datetime.utcnow() - operation = self._collections.get_operation(operation_log.operation) + operation = self._collections.get_operation(operation_rec.operation) # Check if the operation is available for the given host - if operation_log.host and operation_log.host not in operation.host_names: + if operation_rec.host and operation_rec.host not in operation.host_names: logs = ( - f"Operation '{operation_log.operation}' not available for host " - + f"'{operation_log.host}'" + f"Operation '{operation_rec.operation}' not available for host " + + f"'{operation_rec.host}'" ) logger.error(logs) - operation_log.state = OperationStateEnum.FAILURE - operation_log.logs = logs.encode("utf-8") - operation_log.end_time = datetime.utcnow() + operation_rec.state = OperationStateEnum.FAILURE + operation_rec.logs = logs.encode("utf-8") + operation_rec.end_time = datetime.utcnow() return # Execute the operation @@ -71,10 +71,10 @@ def _run_operation(self, operation_log: OperationLog) -> None: ] state, logs = self._executor.execute( playbook=playbook_file, - host=operation_log.host, - extra_vars=operation_log.extra_vars, + host=operation_rec.host, + extra_vars=operation_rec.extra_vars, ) - operation_log.end_time = datetime.utcnow() + operation_rec.end_time = datetime.utcnow() # ? This case shouldn't happen as the executor should return a valid state if state not in OperationStateEnum: @@ -84,8 +84,8 @@ def _run_operation(self, operation_log: OperationLog) -> None: state = OperationStateEnum.FAILURE elif not isinstance(state, OperationStateEnum): state = OperationStateEnum(state) - operation_log.state = state - operation_log.logs = logs + operation_rec.state = state + operation_rec.logs = logs def run( self, diff --git a/tdp/core/models/__init__.py b/tdp/core/models/__init__.py index 141e66b6..06bfc471 100644 --- a/tdp/core/models/__init__.py +++ b/tdp/core/models/__init__.py @@ -14,7 +14,7 @@ NothingToReconfigureError, NothingToResumeError, ) -from tdp.core.models.operation_log import OperationLog +from tdp.core.models.operation_model import OperationModel from tdp.core.models.sch_status_log_model import ( SCHStatusLogModel, SCHStatusLogSourceEnum, diff --git a/tdp/core/models/deployment_model.py b/tdp/core/models/deployment_model.py index 49cd48bd..591d8f4e 100644 --- a/tdp/core/models/deployment_model.py +++ b/tdp/core/models/deployment_model.py @@ -16,7 +16,7 @@ from tdp.core.collections import OPERATION_SLEEP_NAME, OPERATION_SLEEP_VARIABLE from tdp.core.dag import Dag from tdp.core.models.base_model import BaseModel -from tdp.core.models.operation_log import OperationLog +from tdp.core.models.operation_model import OperationModel from tdp.core.models.state_enum import DeploymentStateEnum, OperationStateEnum from tdp.core.utils import BaseEnum @@ -76,9 +76,9 @@ class DeploymentModel(BaseModel): doc="Deployment type." ) - operations: Mapped[list[OperationLog]] = relationship( + operations: Mapped[list[OperationModel]] = relationship( back_populates="deployment", - order_by="OperationLog.operation_order", + order_by="OperationModel.operation_order", cascade="all, delete-orphan", doc="List of operations.", ) @@ -159,7 +159,7 @@ def from_dag( status=DeploymentStateEnum.PLANNED, ) deployment.operations = [ - OperationLog( + OperationModel( operation=operation.name, operation_order=i, host=None, @@ -226,7 +226,7 @@ def from_operations( else [None] ): deployment.operations.append( - OperationLog( + OperationModel( operation=operation.name, operation_order=i, host=host_name, @@ -237,7 +237,7 @@ def from_operations( if can_perform_rolling_restart: i += 1 deployment.operations.append( - OperationLog( + OperationModel( operation=OPERATION_SLEEP_NAME, operation_order=i, host=host_name, @@ -283,7 +283,7 @@ def from_operations_hosts_vars( ) deployment.operations.append( - OperationLog( + OperationModel( operation=operation_name, operation_order=order, host=host_name, @@ -355,7 +355,7 @@ def from_stale_components( operation_order = 1 for operation, host in operation_hosts_sorted: deployment.operations.append( - OperationLog( + OperationModel( operation=operation.name, operation_order=operation_order, host=host, @@ -367,7 +367,7 @@ def from_stale_components( if rolling_interval is not None and operation.action_name == "restart": operation_order += 1 deployment.operations.append( - OperationLog( + OperationModel( operation=OPERATION_SLEEP_NAME, operation_order=operation_order, host=None, @@ -426,7 +426,7 @@ def from_failed_deployment( status=DeploymentStateEnum.PLANNED, ) deployment.operations = [ - OperationLog( + OperationModel( operation=operation, operation_order=i, host=host, diff --git a/tdp/core/models/operation_log.py b/tdp/core/models/operation_model.py similarity index 96% rename from tdp/core/models/operation_log.py rename to tdp/core/models/operation_model.py index 76a82186..11d2aa6f 100644 --- a/tdp/core/models/operation_log.py +++ b/tdp/core/models/operation_model.py @@ -17,8 +17,8 @@ from tdp.core.models import DeploymentModel -class OperationLog(BaseModel): - """Operation log model. +class OperationModel(BaseModel): + """Operation model. Hold past and current operation information linked to a deployment. """ @@ -43,7 +43,7 @@ class OperationLog(BaseModel): start_time: Mapped[Optional[datetime]] = mapped_column(doc="Operation start time.") end_time: Mapped[Optional[datetime]] = mapped_column(doc="Operation end time.") state: Mapped[OperationStateEnum] = mapped_column(doc="Operation state.") - logs: Mapped[Optional[bytes]] = mapped_column(doc="Operation logs.") + logs: Mapped[Optional[bytes]] = mapped_column(doc="Operation.") deployment: Mapped[DeploymentModel] = relationship( back_populates="operations", doc="deployment." diff --git a/tdp/core/models/test_deployment_log.py b/tdp/core/models/test_deployment_log.py index 70fd63cc..d0eccfaa 100644 --- a/tdp/core/models/test_deployment_log.py +++ b/tdp/core/models/test_deployment_log.py @@ -68,7 +68,7 @@ def test_single_operation(self, mock_collections: Collections): deployment = DeploymentModel.from_operations(mock_collections, operations_names) assert [ - operation_log.operation for operation_log in deployment.operations + operation_rec.operation for operation_rec in deployment.operations ] == operations_names assert deployment.deployment_type == DeploymentTypeEnum.OPERATIONS assert deployment.options == {"operations": operations_names} @@ -79,7 +79,7 @@ def test_single_restart_operation(self, mock_collections: Collections): deployment = DeploymentModel.from_operations(mock_collections, operations_names) assert [ - operation_log.operation for operation_log in deployment.operations + operation_rec.operation for operation_rec in deployment.operations ] == operations_names assert deployment.deployment_type == DeploymentTypeEnum.OPERATIONS assert deployment.options == {"operations": operations_names} @@ -90,7 +90,7 @@ def test_single_noop_opeation(self, mock_collections: Collections): deployment = DeploymentModel.from_operations(mock_collections, operations_names) assert [ - operation_log.operation for operation_log in deployment.operations + operation_rec.operation for operation_rec in deployment.operations ] == operations_names assert deployment.deployment_type == DeploymentTypeEnum.OPERATIONS assert deployment.options == {"operations": operations_names} @@ -101,7 +101,7 @@ def test_single_restart_noop_operation(self, mock_collections: Collections): deployment = DeploymentModel.from_operations(mock_collections, operations_names) assert [ - operation_log.operation for operation_log in deployment.operations + operation_rec.operation for operation_rec in deployment.operations ] == operations_names assert deployment.deployment_type == DeploymentTypeEnum.OPERATIONS assert deployment.options == {"operations": operations_names} @@ -112,7 +112,7 @@ def test_multiple_operations(self, mock_collections: Collections): deployment = DeploymentModel.from_operations(mock_collections, operations_names) assert [ - operation_log.operation for operation_log in deployment.operations + operation_rec.operation for operation_rec in deployment.operations ] == operations_names assert deployment.deployment_type == DeploymentTypeEnum.OPERATIONS assert deployment.options == {"operations": operations_names} @@ -126,10 +126,10 @@ def test_single_host(self, mock_collections: Collections): ) assert [ - operation_log.operation for operation_log in deployment.operations + operation_rec.operation for operation_rec in deployment.operations ] == operations_names - for operation_log in deployment.operations: - assert operation_log.host == host + for operation_rec in deployment.operations: + assert operation_rec.host == host assert deployment.deployment_type == DeploymentTypeEnum.OPERATIONS assert deployment.options == { "operations": operations_names, @@ -186,10 +186,10 @@ def test_extra_vars(self, mock_collections: Collections): ) assert [ - operation_log.operation for operation_log in deployment.operations + operation_rec.operation for operation_rec in deployment.operations ] == operations_names - for operation_log in deployment.operations: - assert operation_log.extra_vars == extra_vars + for operation_rec in deployment.operations: + assert operation_rec.extra_vars == extra_vars assert deployment.deployment_type == DeploymentTypeEnum.OPERATIONS assert deployment.options == { "operations": operations_names, @@ -295,8 +295,8 @@ def test_deployment_plan_resume_from_operations_host( resume_deployment.operations ) assert len(deployment.operations) >= len(resume_deployment.operations) - for operation_log in resume_deployment.operations: - assert operation_log.host == host + for operation_rec in resume_deployment.operations: + assert operation_rec.host == host def test_deployment_plan_resume_from_operations_extra_vars( self, mock_collections: Collections @@ -320,8 +320,8 @@ def test_deployment_plan_resume_from_operations_extra_vars( resume_deployment.operations ) assert len(deployment.operations) >= len(resume_deployment.operations) - for operation_log in resume_deployment.operations: - assert operation_log.extra_vars == extra_vars + for operation_rec in resume_deployment.operations: + assert operation_rec.extra_vars == extra_vars @pytest.mark.skip(reason="test to rewrite using cluster_status") diff --git a/tdp/core/models/test_models.py b/tdp/core/models/test_models.py index a8bf550a..f270eab3 100644 --- a/tdp/core/models/test_models.py +++ b/tdp/core/models/test_models.py @@ -6,7 +6,7 @@ from sqlalchemy.orm import Session -from tdp.core.models import DeploymentModel, OperationLog, SCHStatusLogModel +from tdp.core.models import DeploymentModel, OperationModel, SCHStatusLogModel logger = logging.getLogger(__name__) @@ -34,7 +34,7 @@ def test_create_deployment(db_session: Session): host=None, running_version="1.0.0", ) - operation_log = OperationLog( + operation_rec = OperationModel( operation_order=1, deployment_id=deployment.id, operation="start_target1", @@ -45,10 +45,10 @@ def test_create_deployment(db_session: Session): logs=b"operation log", ) - deployment.operations.append(operation_log) + deployment.operations.append(operation_rec) logger.info(deployment) - logger.info(operation_log) + logger.info(operation_rec) logger.info(component_version_log) db_session.add(deployment)