]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
manager: remove systemd support
authorVasek Sraier <git@vakabus.cz>
Fri, 24 Jun 2022 15:20:00 +0000 (17:20 +0200)
committerVasek Sraier <git@vakabus.cz>
Mon, 4 Jul 2022 15:49:58 +0000 (17:49 +0200)
Why? Because it is dangerous to use. You'd have to run manager with root privileges
to be able to spawn systemd services via DBus. There is an option to do the same
with session instances of systemd, but that is unpackageable and pretty much unusable
in production. We will therefore rely on supervisord, as it's support got much better
recently.

manager/knot_resolver_manager/kresd_controller/__init__.py
manager/knot_resolver_manager/kresd_controller/systemd/__init__.py [deleted file]
manager/knot_resolver_manager/kresd_controller/systemd/dbus_api.py [deleted file]
manager/poetry.lock
manager/pyproject.toml
manager/setup.py

index 07d68f76f2cd1027022a138ff05d4d2ec5c9c7a7..0f677d6bfe6bbc69cd1793f1993319e55d469dc0 100644 (file)
@@ -1,6 +1,9 @@
 """
 This file contains autodetection logic for available subprocess controllers. Because we have to catch errors
 from imports, they are located in functions which are invoked at the end of this file.
+
+We supported multiple subprocess controllers while developing it. It now all converged onto just supervisord.
+The interface however remains so that different controllers can be added in the future.
 """
 # pylint: disable=import-outside-toplevel
 
@@ -32,24 +35,6 @@ def try_supervisord():
         logger.error("Failed to import modules related to supervisord service manager", exc_info=True)
 
 
-def try_systemd():
-    """
-    Attempt to load systemd controllers.
-    """
-    try:
-        from knot_resolver_manager.kresd_controller.systemd import SystemdSubprocessController
-        from knot_resolver_manager.kresd_controller.systemd.dbus_api import SystemdType
-
-        _registered_controllers.extend(
-            [
-                SystemdSubprocessController(SystemdType.SYSTEM),
-                SystemdSubprocessController(SystemdType.SESSION),
-            ]
-        )
-    except ImportError:
-        logger.info("Failed to import modules related to systemd service manager")
-
-
 async def get_best_controller_implementation(config: KresConfig) -> SubprocessController:
     logger.debug("Starting service manager auto-selection...")
 
@@ -102,4 +87,3 @@ async def get_controller_by_name(config: KresConfig, name: str) -> SubprocessCon
 
 # run the imports on module load
 try_supervisord()
-try_systemd()
diff --git a/manager/knot_resolver_manager/kresd_controller/systemd/__init__.py b/manager/knot_resolver_manager/kresd_controller/systemd/__init__.py
deleted file mode 100644 (file)
index a5550ac..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-import asyncio
-import logging
-import os
-import re
-from typing import Dict, Iterable, List, Optional, Union
-
-from knot_resolver_manager import compat
-from knot_resolver_manager.compat.asyncio import to_thread
-from knot_resolver_manager.constants import user_constants
-from knot_resolver_manager.datamodel.config_schema import KresConfig
-from knot_resolver_manager.exceptions import SubprocessControllerException
-from knot_resolver_manager.kresd_controller.interface import (
-    KresID,
-    Subprocess,
-    SubprocessController,
-    SubprocessStatus,
-    SubprocessType,
-)
-from knot_resolver_manager.kresd_controller.systemd.dbus_api import (
-    SystemdType,
-    Unit,
-    list_units,
-    reset_failed_unit,
-    restart_unit,
-    start_slice,
-    start_transient_kresd_unit,
-    stop_slice,
-    stop_unit,
-)
-from knot_resolver_manager.utils import phantom_use
-from knot_resolver_manager.utils.async_utils import call
-
-logger = logging.getLogger(__name__)
-
-
-GC_SERVICE_BASE_NAME = "kres-cache-gc-{id}.service"
-KRESD_SERVICE_BASE_NMAE = "kresd-{id}-{num}.service"
-KRESD_SERVICE_BASE_PATTERN = re.compile(r"^kresd-([0-9a-zA-Z]*)-([0-9]+).service$")
-
-
-def _is_service_name_ours(name: str) -> bool:
-    is_ours = name == GC_SERVICE_BASE_NAME.format(id=user_constants().ID)
-    m = KRESD_SERVICE_BASE_PATTERN.match(name)
-    is_ours |= m is not None and m.groups()[0] == user_constants().ID
-    return is_ours
-
-
-class SystemdKresID(KresID):
-    @staticmethod
-    def from_string(val: str) -> "SystemdKresID":
-        if val == GC_SERVICE_BASE_NAME.format(id=user_constants().ID):
-            return SystemdKresID.new(SubprocessType.GC, -1)
-        else:
-            kid = KRESD_SERVICE_BASE_PATTERN.search(val)
-            if kid and kid.groups()[0] == user_constants().ID:
-                return SystemdKresID.new(SubprocessType.KRESD, int(kid.groups()[1]))
-            else:
-                raise RuntimeError("Trying to parse systemd service name which does not match our expectations")
-
-    def __str__(self) -> str:
-        if self.subprocess_type is SubprocessType.GC:
-            return GC_SERVICE_BASE_NAME.format(id=user_constants().ID)
-        elif self.subprocess_type is SubprocessType.KRESD:
-            return KRESD_SERVICE_BASE_NMAE.format(id=user_constants().ID, num=self._id)
-        else:
-            raise RuntimeError(f"Unexpected subprocess type {self.subprocess_type}")
-
-
-class SystemdSubprocess(Subprocess):
-    def __init__(self, config: KresConfig, systemd_type: SystemdType, id_base: Union[SubprocessType, KresID]):
-        if isinstance(id_base, SubprocessType):
-            if id_base is SubprocessType.GC:
-                super().__init__(config, SystemdKresID.new(id_base, -1))
-            else:
-                super().__init__(config, SystemdKresID.alloc(id_base))
-        else:
-            super().__init__(config, id_base)
-        self._systemd_type = systemd_type
-
-    async def _start(self):
-        await compat.asyncio.to_thread(start_transient_kresd_unit, self._config, self._systemd_type, self.id)
-
-    async def _stop(self):
-        await compat.asyncio.to_thread(stop_unit, self._systemd_type, str(self.id))
-
-    async def _restart(self):
-        await compat.asyncio.to_thread(restart_unit, self._systemd_type, str(self.id))
-
-
-class SystemdSubprocessController(SubprocessController):
-    def __init__(self, systemd_type: SystemdType):
-        self._systemd_type = systemd_type
-        self._controller_config: Optional[KresConfig] = None
-
-    def __str__(self):
-        if self._systemd_type == SystemdType.SESSION:
-            return "systemd-session"
-        elif self._systemd_type == SystemdType.SYSTEM:
-            return "systemd"
-        else:
-            raise NotImplementedError("unknown systemd type")
-
-    async def is_controller_available(self, config: KresConfig) -> bool:
-        # communication with systemd is not dependent on the config, its always the same
-        # so we should just make sure, that analysis tools do not complain
-        phantom_use(config)
-
-        # try to run systemctl (should be quite fast)
-        cmd = f"systemctl {'--user' if self._systemd_type == SystemdType.SESSION else ''} status"
-        ret = await call(cmd, shell=True, discard_output=True)
-        if ret != 0:
-            logger.info(
-                "Calling '%s' failed. Assumming systemd (%s) is not running/installed.", cmd, self._systemd_type
-            )
-            return False
-
-        # check that we run under root for non-session systemd
-        try:
-            if self._systemd_type is SystemdType.SYSTEM and os.geteuid() != 0:
-                logger.info(
-                    "Systemd (%s) looks functional, but we are not running as root. Assuming not enough privileges",
-                    self._systemd_type,
-                )
-                return False
-
-            return True
-        except BaseException:  # we want every possible exception to be caught
-            logger.warning("Communicating with systemd DBus API failed", exc_info=True)
-            return False
-
-    async def get_all_running_instances(self) -> Iterable[Subprocess]:
-        assert self._controller_config is not None
-
-        # There are two possibilities (that I knew about when writing this) how to implement this function. We could
-        #
-        # 1. list all units in the system/session
-        # 2. list processes within our slice
-        #
-        # With the list of all units, we would get information about unit states with one DBus method call. However,
-        # there are usually lot of units and the message being passed through DBus is quite big.
-        #
-        # Other option is to query processes within our slice. We can extract service names from the result of the call,
-        # we won't however know whether the units are failed. Actually, we won't know about failed units. This is in
-        # general cheaper as there won't be any processes in the slice. However, missing any failed units would lead to
-        # problems later on - we have to reset state of those. Therefore, we have to query all units and use the first
-        # method.
-        units = await compat.asyncio.to_thread(list_units, self._systemd_type)
-
-        async def load(unit: Unit) -> Optional[SystemdSubprocess]:
-            assert self._controller_config is not None
-
-            if _is_service_name_ours(unit.name):
-                if unit.state == "failed":
-                    # if a unit is failed, remove it from the system by reseting its state
-                    logger.warning("Unit '%s' is already failed, resetting its state and ignoring it", unit.name)
-                    await compat.asyncio.to_thread(reset_failed_unit, self._systemd_type, unit.name)
-                    return None
-
-                return SystemdSubprocess(
-                    self._controller_config,
-                    self._systemd_type,
-                    SystemdKresID.from_string(unit.name),
-                )
-            else:
-                return None
-
-        subprocesses = await asyncio.gather(*[load(name) for name in units])
-        return filter(lambda x: x is not None, subprocesses)  # type: ignore
-
-    async def initialize_controller(self, config: KresConfig) -> None:
-        self._controller_config = config
-        try:
-            await to_thread(start_slice, self._systemd_type)
-        except SubprocessControllerException as e:
-            logger.warning(
-                f"Failed to create systemd slice for our subprocesses: '{e}'. There is/was a manager running with the same ID."
-            )
-
-    async def shutdown_controller(self) -> None:
-        await to_thread(stop_slice, self._systemd_type)
-
-    async def create_subprocess(self, subprocess_config: KresConfig, subprocess_type: SubprocessType) -> Subprocess:
-        assert self._controller_config is not None
-        return SystemdSubprocess(subprocess_config, self._systemd_type, subprocess_type)
-
-    async def get_subprocess_status(self) -> Dict[KresID, SubprocessStatus]:
-        assert self._controller_config is not None
-
-        def convert(val: str) -> SubprocessStatus:
-            status_lookup_table = {"failed": SubprocessStatus.FAILED, "running": SubprocessStatus.RUNNING}
-            if val in status_lookup_table:
-                return status_lookup_table[val]
-            else:
-                return SubprocessStatus.UNKNOWN
-
-        data: List[Unit] = await to_thread(list_units, self._systemd_type)
-
-        our_data = filter(lambda u: _is_service_name_ours(u.name), data)
-        return {SystemdKresID.from_string(u.name): convert(u.state) for u in our_data}
diff --git a/manager/knot_resolver_manager/kresd_controller/systemd/dbus_api.py b/manager/knot_resolver_manager/kresd_controller/systemd/dbus_api.py
deleted file mode 100644 (file)
index 6048fda..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-# pyright: reportUnknownMemberType=false
-# pyright: reportMissingTypeStubs=false
-
-import logging
-import os
-from enum import Enum, auto
-from threading import Thread
-from typing import Any, Callable, Dict, List, Optional, Set, Tuple, TypeVar
-
-from gi.repository import GLib  # type: ignore[import]
-from pydbus import SystemBus  # type: ignore[import]
-from pydbus.bus import SessionBus  # type: ignore[import]
-from typing_extensions import Literal
-
-from knot_resolver_manager.compat.dataclasses import dataclass
-from knot_resolver_manager.constants import (
-    kres_gc_executable,
-    kresd_cache_dir,
-    kresd_config_file,
-    kresd_executable,
-    user_constants,
-)
-from knot_resolver_manager.datamodel.config_schema import KresConfig
-from knot_resolver_manager.exceptions import SubprocessControllerException, SubprocessControllerTimeoutException
-from knot_resolver_manager.kresd_controller.interface import KresID, SubprocessType
-
-logger = logging.getLogger(__name__)
-
-
-class SystemdType(Enum):
-    SYSTEM = auto()
-    SESSION = auto()
-
-
-def _clean_error_message(msg: str) -> str:
-    if "org.freedesktop.systemd1." in msg:
-        msg = msg.split("org.freedesktop.systemd1.", maxsplit=1)[1]
-    return msg
-
-
-T = TypeVar("T")
-
-
-def _wrap_dbus_errors(func: Callable[..., T]) -> Callable[..., T]:
-    def inner(*args: Any, **kwargs: Any) -> T:
-        try:
-            return func(*args, **kwargs)
-        except GLib.Error as e:
-            raise SubprocessControllerException(_clean_error_message(str(e))) from e
-
-    return inner
-
-
-def _create_object_proxy(type_: SystemdType, bus_name: str, path: Optional[str] = None) -> Any:
-    bus: Any = SystemBus() if type_ is SystemdType.SYSTEM else SessionBus()
-    systemd = bus.get(bus_name, path)
-    return systemd
-
-
-def _create_manager_proxy(type_: SystemdType) -> Any:
-    return _create_object_proxy(type_, ".systemd1")
-
-
-def _wait_for_job_completion(systemd: Any, job_creating_func: Callable[[], str], timeout_sec: int = 10) -> None:
-    """
-    Takes a function returning a systemd job path, executes it while simultaneously waiting
-    for its completion. This prevents race conditions.
-    """
-
-    result_state: Optional[str] = None
-    job_path: Optional[str] = None
-
-    def _wait_for_job_completion_handler(loop: Any) -> Any:
-        completed_jobs: Dict[str, str] = {}
-
-        def event_hander(_job_id: Any, path: Any, _unit: Any, state: Any) -> None:
-            nonlocal result_state
-            nonlocal completed_jobs
-
-            # save the current job as completed
-            completed_jobs[path] = state
-
-            if job_path is not None and job_path in completed_jobs:
-                # if we've already seen the job
-                result_state = completed_jobs[job_path]
-                loop.quit()
-
-            # if we already have the job path we are looking for and it's not been seen yet,
-            # it's safe to remove all previous completed job references as we don't care
-            if job_path is not None:
-                completed_jobs.clear()
-
-        return event_hander
-
-    loop: Any = None
-
-    def timeout_stop_loop():
-        nonlocal loop
-        nonlocal result_state
-        result_state = "timeout"
-        loop.quit()
-
-    def event_loop_isolation_thread() -> None:
-        nonlocal loop
-        loop = GLib.MainLoop()
-        GLib.timeout_add_seconds(timeout_sec, timeout_stop_loop)
-        systemd.JobRemoved.connect(_wait_for_job_completion_handler(loop))
-        loop.run()
-
-    # first start the thread to watch for results to prevent race conditions
-    thread = Thread(target=event_loop_isolation_thread, name="glib-loop-isolation-thread")
-    thread.start()
-
-    # then create the job
-    try:
-        job_path = job_creating_func()
-    except BaseException:
-        loop.quit()
-        thread.join()
-        raise
-
-    # then wait for the results
-    thread.join()
-
-    if result_state == "timeout":
-        raise SubprocessControllerTimeoutException(f"systemd job '{job_path}' did not finish in {timeout_sec} seconds")
-    if result_state != "done":
-        raise SubprocessControllerException(
-            f"systemd job '{job_path}' completed with state '{result_state}' instead of expected 'done'"
-        )
-
-
-@_wrap_dbus_errors
-def get_unit_file_state(
-    type_: SystemdType,
-    unit_name: str,
-) -> Literal["disabled", "enabled"]:
-    res = str(_create_manager_proxy(type_).GetUnitFileState(unit_name))
-    assert res == "disabled" or res == "enabled"
-    return res  # type: ignore
-
-
-@dataclass
-class Unit:
-    name: str
-    state: str
-
-
-def _list_units_internal(type_: SystemdType) -> List[Any]:
-    return _create_manager_proxy(type_).ListUnits()
-
-
-@_wrap_dbus_errors
-def list_units(type_: SystemdType) -> List[Unit]:
-    return [Unit(name=str(u[0]), state=str(u[4])) for u in _list_units_internal(type_)]  # type: ignore[call-arg]
-
-
-@_wrap_dbus_errors
-def list_unit_names(type_: SystemdType) -> List[str]:
-    return [str(u[0]) for u in _list_units_internal(type_)]
-
-
-@_wrap_dbus_errors
-def reset_failed_unit(typ: SystemdType, unit_name: str) -> None:
-    systemd = _create_manager_proxy(typ)
-    systemd.ResetFailedUnit(unit_name)
-
-
-@_wrap_dbus_errors
-def _list_slice_services(typ: SystemdType, slice_name: str) -> Set[str]:
-    # uses DBus method call, which is not documented, but is present since 2016 and is used by `systemctl status`
-    # appears for the first time in commit 291d565a04263452c03beaf537773ade4f0b1617 in systemd
-
-    systemd = _create_manager_proxy(typ)
-    data = systemd.GetUnitProcesses(slice_name)
-    return set((p[0].split("/")[-1] for p in data))
-
-
-@_wrap_dbus_errors
-def restart_unit(type_: SystemdType, unit_name: str) -> None:
-    systemd = _create_manager_proxy(type_)
-
-    def job():
-        return systemd.RestartUnit(unit_name, "fail")
-
-    _wait_for_job_completion(systemd, job)
-
-
-def _slice_name() -> str:
-    return f"kres-{user_constants().ID}.slice"
-
-
-def _kresd_unit_properties(config: KresConfig, kres_id: KresID) -> List[Tuple[str, str]]:
-    val: Any = [
-        ("Description", GLib.Variant("s", "transient Knot Resolver unit started by Knot Resolver Manager")),
-        ("Type", GLib.Variant("s", "notify")),
-        ("WorkingDirectory", GLib.Variant("s", os.getcwd())),
-        (
-            "ExecStart",
-            GLib.Variant(
-                "a(sasb)",
-                [
-                    (
-                        str(kresd_executable()),
-                        [str(kresd_executable()), "-c", str(kresd_config_file(config, kres_id)), "-n"],
-                        False,
-                    )
-                ],
-            ),
-        ),
-        ("TimeoutStopUSec", GLib.Variant("t", 10000000)),
-        # The manager assumes that the subprocess is always running. When this is not the case, we end up with a hard
-        # crash, because no code is expecting to deal with this state. Therefore, there is no condition under which
-        # kresd instances could be not running ==> we configure systemd to restart them always
-        ("Restart", GLib.Variant("s", "always")),
-        ("LimitNOFILE", GLib.Variant("t", 524288)),
-        ("Environment", GLib.Variant("as", [f"SYSTEMD_INSTANCE={kres_id}"])),
-        ("Slice", GLib.Variant("s", _slice_name())),
-    ]
-
-    if config.supervisor.watchdog:
-        val.append(
-            ("WatchdogUSec", GLib.Variant("t", 10000000)),
-        )
-
-    return val
-
-
-def _gc_unit_properties(config: KresConfig) -> Any:
-    val: Any = [
-        (
-            "Description",
-            GLib.Variant("s", "transient Knot Resolver Garbage Collector unit started by Knot Resolver Manager"),
-        ),
-        ("Type", GLib.Variant("s", "simple")),
-        ("WorkingDirectory", GLib.Variant("s", os.getcwd())),
-        (
-            "ExecStart",
-            GLib.Variant(
-                "a(sasb)",
-                [
-                    (
-                        str(kres_gc_executable()),
-                        [str(kres_gc_executable()), "-c", str(kresd_cache_dir(config)), "-d", "1000"],
-                        True,
-                    )
-                ],
-            ),
-        ),
-        ("Restart", GLib.Variant("s", "always")),  # see reasoning at kresd instance properties
-        ("RestartUSec", GLib.Variant("t", 30000000)),
-        ("StartLimitIntervalUSec", GLib.Variant("t", 400000000)),
-        ("StartLimitBurst", GLib.Variant("u", 10)),
-        ("Slice", GLib.Variant("s", _slice_name())),
-    ]
-    return val
-
-
-def _kres_slice_properties() -> Any:
-    val: Any = [
-        ("Description", GLib.Variant("s", "Knot Resolver processes")),
-    ]
-    return val
-
-
-@_wrap_dbus_errors
-def _start_transient_unit(systemd_type: SystemdType, name: str, properties: Any) -> None:
-    systemd = _create_manager_proxy(systemd_type)
-
-    def job():
-        return systemd.StartTransientUnit(name, "fail", properties, [])
-
-    try:
-        _wait_for_job_completion(systemd, job)
-    except SubprocessControllerTimeoutException:
-        logger.error(
-            f"Failed to start transient '{name}'. The start operation did not finish within the expected timeframe"
-        )
-        raise
-    except SubprocessControllerException as e:
-        logger.error(f"Failed to start transient '{name}':")
-        for (k, v) in properties:
-            logger.error(f"    {k}={v}")
-        logger.error(f"More useful details might be found in the service's log by running 'journalctl -u {name}'")
-        raise SubprocessControllerException(f"Failed to start systemd transient service '{name}': {e}") from e
-
-
-def start_transient_kresd_unit(config: KresConfig, type_: SystemdType, kres_id: KresID) -> None:
-    properties = {
-        SubprocessType.KRESD: _kresd_unit_properties(config, kres_id),
-        SubprocessType.GC: _gc_unit_properties(config),
-    }[kres_id.subprocess_type]
-    name = str(kres_id)
-
-    _start_transient_unit(type_, name, properties)
-
-
-def start_slice(systemd_type: SystemdType) -> None:
-    _start_transient_unit(systemd_type, _slice_name(), _kres_slice_properties())
-
-
-def stop_slice(systemd_type: SystemdType) -> None:
-    stop_unit(systemd_type, _slice_name())
-
-
-def list_our_slice_processes(systemd_type: SystemdType) -> Set[str]:
-    return _list_slice_services(systemd_type, _slice_name())
-
-
-@_wrap_dbus_errors
-def start_unit(type_: SystemdType, unit_name: str) -> None:
-    systemd = _create_manager_proxy(type_)
-
-    def job() -> Any:
-        return systemd.StartUnit(unit_name, "fail")
-
-    _wait_for_job_completion(systemd, job)
-
-
-@_wrap_dbus_errors
-def stop_unit(type_: SystemdType, unit_name: str) -> None:
-    systemd = _create_manager_proxy(type_)
-
-    def job() -> Any:
-        return systemd.StopUnit(unit_name, "fail")
-
-    _wait_for_job_completion(systemd, job)
-
-
-@_wrap_dbus_errors
-def list_unit_files(type_: SystemdType) -> List[str]:
-    systemd = _create_manager_proxy(type_)
-    files = systemd.ListUnitFiles()
-    return [str(x[0]) for x in files]
-
-
-@_wrap_dbus_errors
-def is_unit_failed(typ: SystemdType, unit_name: str) -> bool:
-    systemd = _create_manager_proxy(typ)
-    unit_path = systemd.LoadUnit(unit_name)
-    unit_object = _create_object_proxy(typ, ".systemd1", unit_path)
-    return unit_object.ActiveState == "failed"
-
-
-@_wrap_dbus_errors
-def can_load_unit(type_: SystemdType, unit_name: str) -> bool:
-    systemd = _create_manager_proxy(type_)
-    try:
-        unit_path: str = systemd.LoadUnit(unit_name)
-        unit_object = _create_object_proxy(type_, ".systemd1", unit_path)
-        load_error = unit_object.LoadError
-        return load_error == ("", "")
-    except Exception:
-        # if this fails in any way, we can assume that the unit is not properly loaded
-        return False
index bb670f61175ce9e60af6d2582bd49833cac85479..08e206fb695f452e025ac92bd400b8b9c0845394 100644 (file)
@@ -139,7 +139,7 @@ d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
 
 [[package]]
 name = "cachecontrol"
-version = "0.12.10"
+version = "0.12.11"
 description = "httplib2 caching for requests"
 category = "dev"
 optional = false
@@ -645,7 +645,7 @@ tomlkit = ">=0.6.0,<1.0.0"
 
 [[package]]
 name = "poetry"
-version = "1.1.12"
+version = "1.1.13"
 description = "Python dependency management and packaging made easy."
 category = "dev"
 optional = false
@@ -659,7 +659,7 @@ clikit = ">=0.6.2,<0.7.0"
 crashtest = {version = ">=0.3.0,<0.4.0", markers = "python_version >= \"3.6\" and python_version < \"4.0\""}
 html5lib = ">=1.0,<2.0"
 importlib-metadata = {version = ">=1.6.0,<2.0.0", markers = "python_version < \"3.8\""}
-keyring = {version = ">=21.2.0,<22.0.0", markers = "python_version >= \"3.6\" and python_version < \"4.0\""}
+keyring = {version = ">=21.2.0", markers = "python_version >= \"3.6\" and python_version < \"4.0\""}
 packaging = ">=20.4,<21.0"
 pexpect = ">=4.7.0,<5.0.0"
 pkginfo = ">=1.4,<2.0"
@@ -708,14 +708,6 @@ category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
-[[package]]
-name = "pycairo"
-version = "1.20.1"
-description = "Python interface for cairo"
-category = "main"
-optional = false
-python-versions = ">=3.6, <4"
-
 [[package]]
 name = "pycodestyle"
 version = "2.7.0"
@@ -732,14 +724,6 @@ category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
-[[package]]
-name = "pydbus"
-version = "0.6.0"
-description = "Pythonic DBus library"
-category = "main"
-optional = false
-python-versions = "*"
-
 [[package]]
 name = "pyflakes"
 version = "2.3.1"
@@ -756,17 +740,6 @@ category = "dev"
 optional = false
 python-versions = ">=3.5"
 
-[[package]]
-name = "pygobject"
-version = "3.42.0"
-description = "Python bindings for GObject Introspection"
-category = "main"
-optional = false
-python-versions = ">=3.6, <4"
-
-[package.dependencies]
-pycairo = ">=1.16,<2.0"
-
 [[package]]
 name = "pylev"
 version = "1.4.0"
@@ -1279,7 +1252,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.6.8"
-content-hash = "d623052939bf87e455b7193e41aa06582ecc2db154da2cb5c2c77a183876186f"
+content-hash = "92ad4d1a4308502d5b4e74f407c8a3f4299f45c1a17061af160343f89befab4e"
 
 [metadata.files]
 aiohttp = [
@@ -1396,8 +1369,8 @@ black = [
     {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"},
 ]
 cachecontrol = [
-    {file = "CacheControl-0.12.10-py2.py3-none-any.whl", hash = "sha256:b0d43d8f71948ef5ebdee5fe236b86c6ffc7799370453dccb0e894c20dfa487c"},
-    {file = "CacheControl-0.12.10.tar.gz", hash = "sha256:d8aca75b82eec92d84b5d6eb8c8f66ea16f09d2adb09dbca27fe2d5fc8d3732d"},
+    {file = "CacheControl-0.12.11-py2.py3-none-any.whl", hash = "sha256:2c75d6a8938cb1933c75c50184549ad42728a27e9f6b92fd677c3151aa72555b"},
+    {file = "CacheControl-0.12.11.tar.gz", hash = "sha256:a5b9fcc986b184db101aa280b42ecdcdfc524892596f606858e0b7a8b4d9e144"},
 ]
 cachy = [
     {file = "cachy-0.3.0-py2.py3-none-any.whl", hash = "sha256:338ca09c8860e76b275aff52374330efedc4d5a5e45dc1c5b539c1ead0786fe7"},
@@ -1966,8 +1939,8 @@ poethepoet = [
     {file = "poethepoet-0.9.0.tar.gz", hash = "sha256:ab2263fd7be81d16d38a4b4fe42a055d992d04421e61cad36498b1e4bd8ee2a6"},
 ]
 poetry = [
-    {file = "poetry-1.1.12-py2.py3-none-any.whl", hash = "sha256:3d4dc5d4c7171fb251b32e49a98cecbe2795d5e681ecee2297e2b2d2ccd671fc"},
-    {file = "poetry-1.1.12.tar.gz", hash = "sha256:5c66e2357fe37b552462a88b7d31bfa2ed8e84172208becd666933c776252567"},
+    {file = "poetry-1.1.13-py2.py3-none-any.whl", hash = "sha256:52deb0792a2e801967ba9c4cdb39b56fe68b0b5cd3f195b004bef603db9d51a7"},
+    {file = "poetry-1.1.13.tar.gz", hash = "sha256:b905ed610085f568aa61574e0e09260c02bff9eae12ff672af39e9f399357ac4"},
 ]
 poetry-core = [
     {file = "poetry-core-1.0.7.tar.gz", hash = "sha256:98c11c755a16ef6c5673c22ca94a3802a7df4746a0853a70b6fae8b9f5cac206"},
@@ -1984,19 +1957,6 @@ py = [
     {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
     {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
 ]
-pycairo = [
-    {file = "pycairo-1.20.1-cp310-cp310-win32.whl", hash = "sha256:736ffc618e851601e861a630293e5c910ef016b83b2d035a336f83a367bf56ab"},
-    {file = "pycairo-1.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:261c69850d4b2ec03346c9745bad2a835bb8124e4c6961b8ceac503d744eb3b3"},
-    {file = "pycairo-1.20.1-cp36-cp36m-win32.whl", hash = "sha256:6db823a18e7be1eb2a29c28961f2f01e84d3b449f06be7338d05ac8f90592cd5"},
-    {file = "pycairo-1.20.1-cp36-cp36m-win_amd64.whl", hash = "sha256:5525da2d8de912750dd157752aa96f1f0a42a437c5625e85b14c936b5c6305ae"},
-    {file = "pycairo-1.20.1-cp37-cp37m-win32.whl", hash = "sha256:c8c2bb933974d91c5d19e54b846d964de177e7bf33433bf34ac34c85f9b30e94"},
-    {file = "pycairo-1.20.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9a32e4a3574a104aa876c35d5e71485dfd6986b18d045534c6ec510c44d5d6a7"},
-    {file = "pycairo-1.20.1-cp38-cp38-win32.whl", hash = "sha256:0d7a6754d410d911a46f00396bee4be96500ccd3d178e7e98aef1140e3dd67ae"},
-    {file = "pycairo-1.20.1-cp38-cp38-win_amd64.whl", hash = "sha256:b605151cdd23cedb31855b8666371b6e26b80f02753a52c8b8023a916b1df812"},
-    {file = "pycairo-1.20.1-cp39-cp39-win32.whl", hash = "sha256:e800486b51fffeb11ed867b4f2220d446e2a60a81a73b7c377123e0cbb72f49d"},
-    {file = "pycairo-1.20.1-cp39-cp39-win_amd64.whl", hash = "sha256:f123d3818e30b77b7209d70a6dcfd5b4e34885f9fa539d92dd7ff3e4e2037213"},
-    {file = "pycairo-1.20.1.tar.gz", hash = "sha256:1ee72b035b21a475e1ed648e26541b04e5d7e753d75ca79de8c583b25785531b"},
-]
 pycodestyle = [
     {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
     {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
@@ -2005,10 +1965,6 @@ pycparser = [
     {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
     {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
 ]
-pydbus = [
-    {file = "pydbus-0.6.0-py2.py3-none-any.whl", hash = "sha256:66b80106352a718d80d6c681dc2a82588048e30b75aab933e4020eb0660bf85e"},
-    {file = "pydbus-0.6.0.tar.gz", hash = "sha256:4207162eff54223822c185da06c1ba8a34137a9602f3da5a528eedf3f78d0f2c"},
-]
 pyflakes = [
     {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
     {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
@@ -2017,9 +1973,6 @@ pygments = [
     {file = "Pygments-2.11.1-py3-none-any.whl", hash = "sha256:9135c1af61eec0f650cd1ea1ed8ce298e54d56bcd8cc2ef46edd7702c171337c"},
     {file = "Pygments-2.11.1.tar.gz", hash = "sha256:59b895e326f0fb0d733fd28c6839bd18ad0687ba20efc26d4277fd1d30b971f4"},
 ]
-pygobject = [
-    {file = "PyGObject-3.42.0.tar.gz", hash = "sha256:b9803991ec0b0b4175e81fee0ad46090fa7af438fe169348a9b18ae53447afcd"},
-]
 pylev = [
     {file = "pylev-1.4.0-py2.py3-none-any.whl", hash = "sha256:7b2e2aa7b00e05bb3f7650eb506fc89f474f70493271a35c242d9a92188ad3dd"},
     {file = "pylev-1.4.0.tar.gz", hash = "sha256:9e77e941042ad3a4cc305dcdf2b2dec1aec2fbe3dd9015d2698ad02b173006d1"},
index 9f646c041bf80c85c3cff7e4b3fa8ffe2a87fc47..63676b5698c27fb39dc8763a4d3cc13576b78a37 100644 (file)
@@ -16,8 +16,6 @@ generate-setup-file = true
 [tool.poetry.dependencies]
 python = "^3.6.8"
 aiohttp = "^3.6.12"
-pydbus = "^0.6.0"
-PyGObject = "^3.38.0"
 Jinja2 = "^2.11.3"
 click = "^7.1.2"
 PyYAML = "^5.4.1"
index ca4bac74b0a980a3f8cd05da28f2352a9fdbbe04..d4e2f3cdd567f9074132afec389def1f09eace77 100644 (file)
@@ -10,7 +10,6 @@ packages = \
  'knot_resolver_manager.kresd_controller',
  'knot_resolver_manager.kresd_controller.supervisord',
  'knot_resolver_manager.kresd_controller.supervisord.plugin',
- 'knot_resolver_manager.kresd_controller.systemd',
  'knot_resolver_manager.utils']
 
 package_data = \
@@ -19,12 +18,10 @@ package_data = \
 
 install_requires = \
 ['Jinja2>=2.11.3',
- 'PyGObject>=3.38.0',
  'PyYAML>=5.4.1',
  'aiohttp>=3.6.12',
  'click>=7.1.2',
  'prometheus-client>=0.6',
- 'pydbus>=0.6.0',
  'requests>=2.25.1',
  'typing-extensions>=3.7.2']