def test_update_self(client: Client) -> None: """ must update self status without errors """ client.update_self(BuildStatusEnum.Unknown)
class Lock: """ wrapper for application lock file :ivar force: remove lock file on start if any :ivar path: path to lock file if any :ivar reporter: build status reporter instance :ivar root: repository root (i.e. ahriman home) :ivar unsafe: skip user check """ def __init__(self, args: argparse.Namespace, architecture: str, configuration: Configuration) -> None: """ default constructor :param args: command line args :param architecture: repository architecture :param configuration: configuration instance """ self.path = Path( f"{args.lock}_{architecture}") if args.lock is not None else None self.force = args.force self.unsafe = args.unsafe self.root = Path(configuration.get("repository", "root")) self.reporter = Client() if args.no_report else Client.load( configuration) def __enter__(self) -> Lock: """ default workflow is the following: check user UID check if there is lock file check web status watcher status create lock file report to web if enabled """ self.check_user() self.check_version() self.create() self.reporter.update_self(BuildStatusEnum.Building) return self def __exit__(self, exc_type: Optional[Type[Exception]], exc_val: Optional[Exception], exc_tb: TracebackType) -> Literal[False]: """ remove lock file when done :param exc_type: exception type name if any :param exc_val: exception raised if any :param exc_tb: exception traceback if any :return: always False (do not suppress any exception) """ self.clear() status = BuildStatusEnum.Success if exc_val is None else BuildStatusEnum.Failed self.reporter.update_self(status) return False def check_version(self) -> None: """ check web server version """ status = self.reporter.get_internal() if status.version is not None and status.version != version.__version__: logging.getLogger("root").warning( f"status watcher version mismatch, " f"our {version.__version__}, their {status.version}") def check_user(self) -> None: """ check if current user is actually owner of ahriman root """ if self.unsafe: return current_uid = os.getuid() root_uid = self.root.stat().st_uid if current_uid != root_uid: raise UnsafeRun(current_uid, root_uid) def clear(self) -> None: """ remove lock file """ if self.path is None: return self.path.unlink(missing_ok=True) def create(self) -> None: """ create lock file """ if self.path is None: return try: self.path.touch(exist_ok=self.force) except FileExistsError: raise DuplicateRun()