Added ipdb as breakpoint console. Improved logging.

This commit is contained in:
Qubasa
2023-10-18 18:29:10 +02:00
parent af3f04736b
commit 9f464dd14e
10 changed files with 58 additions and 26 deletions

View File

@@ -1,6 +1,7 @@
import logging import logging
from typing import Any, Callable from typing import Any, Callable
from pathlib import Path from pathlib import Path
import inspect
grey = "\x1b[38;20m" grey = "\x1b[38;20m"
yellow = "\x1b[33;20m" yellow = "\x1b[33;20m"
@@ -10,10 +11,16 @@ green = "\u001b[32m"
blue = "\u001b[34m" blue = "\u001b[34m"
def get_formatter(color: str) -> Callable[[logging.LogRecord], logging.Formatter]:
def myformatter(record: logging.LogRecord) -> logging.Formatter: def get_formatter(color: str) -> Callable[[logging.LogRecord, bool], logging.Formatter]:
def myformatter(record: logging.LogRecord, with_location: bool) -> logging.Formatter:
reset = "\x1b[0m" reset = "\x1b[0m"
filepath = Path(record.pathname).resolve() filepath = Path(record.pathname).resolve()
if not with_location:
return logging.Formatter(
f"{color}%(levelname)s{reset}: %(message)s"
)
return logging.Formatter( return logging.Formatter(
f"{color}%(levelname)s{reset}: %(message)s\n {filepath}:%(lineno)d::%(funcName)s\n" f"{color}%(levelname)s{reset}: %(message)s\n {filepath}:%(lineno)d::%(funcName)s\n"
) )
@@ -31,11 +38,32 @@ FORMATTER = {
class CustomFormatter(logging.Formatter): class CustomFormatter(logging.Formatter):
def format(self, record: logging.LogRecord) -> str: def format(self, record: logging.LogRecord) -> str:
return FORMATTER[record.levelno](record).format(record) return FORMATTER[record.levelno](record, True).format(record)
class ThreadFormatter(logging.Formatter):
def format(self, record: logging.LogRecord) -> str:
return FORMATTER[record.levelno](record, False).format(record)
def get_caller() -> str:
frame = inspect.currentframe()
if frame is None:
return "unknown"
caller_frame = frame.f_back
if caller_frame is None:
return "unknown"
caller_frame = caller_frame.f_back
if caller_frame is None:
return "unknown"
frame_info = inspect.getframeinfo(caller_frame)
ret = f"{frame_info.filename}:{frame_info.lineno}::{frame_info.function}"
return ret
def register(level: Any) -> None: def register(level: Any) -> None:
ch = logging.StreamHandler() handler = logging.StreamHandler()
ch.setLevel(level) handler.setLevel(level)
ch.setFormatter(CustomFormatter()) handler.setFormatter(CustomFormatter())
logging.basicConfig(level=level, handlers=[ch]) logger = logging.getLogger("registerHandler")
logger.addHandler(handler)
#logging.basicConfig(level=level, handlers=[handler])

View File

@@ -95,6 +95,7 @@ def generate_secrets_from_nix(
) -> None: ) -> None:
generate_host_key(flake_name, machine_name) generate_host_key(flake_name, machine_name)
errors = {} errors = {}
with TemporaryDirectory() as d: with TemporaryDirectory() as d:
# if any of the secrets are missing, we regenerate all connected facts/secrets # if any of the secrets are missing, we regenerate all connected facts/secrets
for secret_group, secret_options in secret_submodules.items(): for secret_group, secret_options in secret_submodules.items():

View File

@@ -12,6 +12,7 @@ from pathlib import Path
from typing import Any, Iterator, Optional, Type, TypeVar from typing import Any, Iterator, Optional, Type, TypeVar
from uuid import UUID, uuid4 from uuid import UUID, uuid4
from .custom_logger import get_caller, ThreadFormatter, CustomFormatter
from .errors import ClanError from .errors import ClanError
@@ -38,7 +39,8 @@ class Command:
cwd: Optional[Path] = None, cwd: Optional[Path] = None,
) -> None: ) -> None:
self.running = True self.running = True
self.log.debug(f"Running command: {shlex.join(cmd)}") self.log.debug(f"Command: {shlex.join(cmd)}")
self.log.debug(f"Caller: {get_caller()}")
cwd_res = None cwd_res = None
if cwd is not None: if cwd is not None:
@@ -94,7 +96,13 @@ class BaseTask:
def __init__(self, uuid: UUID, num_cmds: int) -> None: def __init__(self, uuid: UUID, num_cmds: int) -> None:
# constructor # constructor
self.uuid: UUID = uuid self.uuid: UUID = uuid
self.log = logging.getLogger(__name__) handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
handler.setFormatter(ThreadFormatter())
logger = logging.getLogger(__name__)
logger.addHandler(handler)
self.log = logger
self.log = logger
self.procs: list[Command] = [] self.procs: list[Command] = []
self.status = TaskStatus.NOTSTARTED self.status = TaskStatus.NOTSTARTED
self.logs_lock = threading.Lock() self.logs_lock = threading.Lock()

View File

@@ -13,6 +13,7 @@ from ..dirs import specific_flake_dir
from ..nix import nix_build, nix_config, nix_shell from ..nix import nix_build, nix_config, nix_shell
from ..task_manager import BaseTask, Command, create_task from ..task_manager import BaseTask, Command, create_task
from .inspect import VmConfig, inspect_vm from .inspect import VmConfig, inspect_vm
import pydantic
class BuildVmTask(BaseTask): class BuildVmTask(BaseTask):
@@ -58,6 +59,7 @@ class BuildVmTask(BaseTask):
env = os.environ.copy() env = os.environ.copy()
env["CLAN_DIR"] = str(self.vm.flake_url) env["CLAN_DIR"] = str(self.vm.flake_url)
env["PYTHONPATH"] = str( env["PYTHONPATH"] = str(
":".join(sys.path) ":".join(sys.path)
) # TODO do this in the clanCore module ) # TODO do this in the clanCore module
@@ -70,7 +72,7 @@ class BuildVmTask(BaseTask):
env=env, env=env,
) )
else: else:
cmd.run(["echo", "won't generate secrets for non local clan"]) self.log.warning("won't generate secrets for non local clan")
cmd = next(cmds) cmd = next(cmds)
cmd.run( cmd.run(

View File

@@ -12,6 +12,7 @@ log = logging.getLogger(__name__)
def validate_path(base_dir: Path, value: Path) -> Path: def validate_path(base_dir: Path, value: Path) -> Path:
user_path = (base_dir / value).resolve() user_path = (base_dir / value).resolve()
# Check if the path is within the data directory # Check if the path is within the data directory
if not str(user_path).startswith(str(base_dir)): if not str(user_path).startswith(str(base_dir)):
if not str(user_path).startswith("/tmp/pytest"): if not str(user_path).startswith("/tmp/pytest"):

View File

@@ -11,6 +11,8 @@
, pytest-xdist , pytest-xdist
, pytest-subprocess , pytest-subprocess
, pytest-timeout , pytest-timeout
, remote-pdb
, ipdb
, python3 , python3
, runCommand , runCommand
, setuptools , setuptools
@@ -47,6 +49,8 @@ let
pytest-subprocess pytest-subprocess
pytest-xdist pytest-xdist
pytest-timeout pytest-timeout
remote-pdb
ipdb
openssh openssh
git git
gnupg gnupg

View File

@@ -20,7 +20,7 @@ clan_cli = [ "config/jsonschema/*", "webui/assets/**/*"]
testpaths = "tests" testpaths = "tests"
faulthandler_timeout = 60 faulthandler_timeout = 60
log_level = "DEBUG" log_level = "DEBUG"
log_format = "%(levelname)s: %(message)s\n %(pathname)s:%(lineno)d::%(funcName)s" log_format = "%(levelname)s: %(message)s"
addopts = "--cov . --cov-report term --cov-report html:.reports/html --no-cov-on-fail --durations 5 --color=yes --maxfail=1 --new-first -nauto" # Add --pdb for debugging addopts = "--cov . --cov-report term --cov-report html:.reports/html --no-cov-on-fail --durations 5 --color=yes --maxfail=1 --new-first -nauto" # Add --pdb for debugging
norecursedirs = "tests/helpers" norecursedirs = "tests/helpers"
markers = [ "impure" ] markers = [ "impure" ]

View File

@@ -43,6 +43,7 @@ mkShell {
export PATH="$tmp_path/python/bin:${checkScript}/bin:$PATH" export PATH="$tmp_path/python/bin:${checkScript}/bin:$PATH"
export PYTHONPATH="$source:$tmp_path/python/${pythonWithDeps.sitePackages}:" export PYTHONPATH="$source:$tmp_path/python/${pythonWithDeps.sitePackages}:"
export PYTHONBREAKPOINT=ipdb.set_trace
export XDG_DATA_DIRS="$tmp_path/share''${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}" export XDG_DATA_DIRS="$tmp_path/share''${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"
export fish_complete_path="$tmp_path/share/fish/vendor_completions.d''${fish_complete_path:+:$fish_complete_path}" export fish_complete_path="$tmp_path/share/fish/vendor_completions.d''${fish_complete_path:+:$fish_complete_path}"

View File

@@ -4,24 +4,11 @@ import logging
import shlex import shlex
from clan_cli import create_parser from clan_cli import create_parser
from clan_cli.custom_logger import get_caller
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def get_caller() -> str:
frame = inspect.currentframe()
if frame is None:
return "unknown"
caller_frame = frame.f_back
if caller_frame is None:
return "unknown"
caller_frame = caller_frame.f_back
if caller_frame is None:
return "unknown"
frame_info = inspect.getframeinfo(caller_frame)
ret = f"{frame_info.filename}:{frame_info.lineno}::{frame_info.function}"
return ret
class Cli: class Cli:
def __init__(self) -> None: def __init__(self) -> None: