from knot_resolver_manager.datamodel.slice_schema import SliceSchema
from knot_resolver_manager.datamodel.static_hints_schema import StaticHintsSchema
from knot_resolver_manager.datamodel.stub_zone_schema import StubZoneSchema
-from knot_resolver_manager.datamodel.types import AbsoluteDir, IntPositive
+from knot_resolver_manager.datamodel.types import IntPositive
+from knot_resolver_manager.datamodel.types.files import UncheckedPath
from knot_resolver_manager.datamodel.view_schema import ViewSchema
from knot_resolver_manager.datamodel.webmgmt_schema import WebmgmtSchema
from knot_resolver_manager.utils.modeling import ConfigSchema
version: int = 1
nsid: Optional[str] = None
hostname: Optional[str] = None
- rundir: AbsoluteDir = AbsoluteDir("/var/run/knot-resolver")
+ rundir: UncheckedPath = UncheckedPath("/var/run/knot-resolver")
workers: Union[Literal["auto"], IntPositive] = IntPositive(1)
max_workers: IntPositive = IntPositive(_default_max_worker_count())
management: ManagementSchema = ManagementSchema({"unix-socket": "./manager.sock"})
nsid: Optional[str]
hostname: str
- rundir: AbsoluteDir
+ rundir: UncheckedPath
workers: IntPositive
max_workers: IntPositive
management: ManagementSchema
# it should be removed and relative path used instead as soon as issue
# https://gitlab.nic.cz/knot/knot-resolver/-/issues/720 is fixed
return _MAIN_TEMPLATE.render(cfg=self, cwd=os.getcwd()) # pyright: reportUnknownMemberType=false
+
+
+def get_rundir_without_validation(data: Dict[str, Any]) -> UncheckedPath:
+ """
+ Without fully parsing, try to get a rundir from a raw config data. When it fails,
+ attempts a full validation to produce a good error message.
+
+ Used for initial manager startup.
+ """
+
+ if "rundir" in data:
+ rundir = data["rundir"]
+ else:
+ _ = KresConfig(data) # this should throw a descriptive error
+ assert False
+
+ return UncheckedPath(rundir)
) -> None:
super().__init__(source_value, parents=parents, object_path=object_path)
if not self._value.is_dir():
- raise ValueError("path does not point to an existing directory")
+ raise ValueError(f"path '{self._value}' does not point to an existing directory")
class AbsoluteDir(Dir):
super().__init__(source_value, parents=parents, object_path=object_path)
p = self._value.parent
if not p.exists() or not p.is_dir():
- raise ValueError("path does not point inside an existing directory")
+ raise ValueError(f"path '{self._value}' does not point inside an existing directory")
if self._value.is_dir():
raise ValueError("path points to a directory when we expected a file")
from knot_resolver_manager.compat import asyncio as asyncio_compat
from knot_resolver_manager.config_store import ConfigStore
from knot_resolver_manager.constants import DEFAULT_MANAGER_CONFIG_FILE, PID_FILE_NAME, init_user_constants
-from knot_resolver_manager.datamodel.config_schema import KresConfig
+from knot_resolver_manager.datamodel.config_schema import KresConfig, get_rundir_without_validation
from knot_resolver_manager.datamodel.management_schema import ManagementSchema
from knot_resolver_manager.exceptions import CancelStartupExecInsteadException, KresManagerException
from knot_resolver_manager.kresd_controller import get_best_controller_implementation
def _set_working_directory(config_raw: Dict[str, Any]) -> None:
- config = KresConfig(config_raw)
+ rundir = get_rundir_without_validation(config_raw)
- if not config.rundir.to_path().exists():
- raise KresManagerException(f"`rundir` directory ({config.rundir}) does not exist!")
+ if not rundir.to_path().exists():
+ raise KresManagerException(f"`rundir` directory ({rundir}) does not exist!")
- os.chdir(config.rundir.to_path())
+ logger.info("changing working directory to rundir at '%s'", rundir.to_path().absolute())
+ os.chdir(rundir.to_path())
def _lock_working_directory(attempt: int = 0) -> None:
config_raw = await _load_raw_config(config)
# We want to change cwd as soon as possible. Especially before any real config validation, because cwd
- # is used for resolving relative paths. Thats also a reason, why in practice, we validate the config twice.
- # Once when setting up the cwd just to read the `rundir` property. When cwd is set, we do it again to resolve
- # all paths correctly.
- # Note: the first config validation is done here - therefore all initial config validation errors will
- # originate from here.
+ # is used for resolving relative paths. If we fail to read rundir from unparsed config, a full validation
+ # error will come from here. If we are successfull, full validation will be done further on when initializing
+ # the config store.
_set_working_directory(config_raw)
# We don't want more than one manager in a single working directory. So we lock it with a PID file.