Ejemplo n.º 1
0
def test_get_internal(client: Client) -> None:
    """
    must return dummy status for web service
    """
    assert client.get_internal() == InternalStatus()
Ejemplo n.º 2
0
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()