Source code for ldap_sync.execution
# Copyright (c) 2022. The Pycroft Authors. See the AUTHORS file.
# This file is part of the Pycroft project and licensed under the terms of
# the Apache License, Version 2.0. See the LICENSE file for details
"""
ldap_sync.execution
~~~~~~~~~~~~~~~~~~~
Execution strategies for an :class:`Action`.
Concretely, the real one and the dry-run.
"""
import functools
import logging
import ldap3
from ldap_sync.concepts.action import (
Action,
AddAction,
DeleteAction,
ModifyAction,
IdleAction,
)
[docs]
@functools.singledispatch
def execute_real(action: Action, connection: ldap3.Connection) -> None:
raise TypeError(f"No dispatch defined for action of type {type(action).__name__}")
@execute_real.register
def _(action: AddAction, connection: ldap3.Connection) -> None:
action.logger.debug("Executing %s for %s", type(action).__name__, action.record_dn)
action.logger.debug("Attributes used: %s", action.nonempty_attrs)
connection.add(action.record_dn, attributes=action.nonempty_attrs)
debug_whether_success(action.logger, connection)
@execute_real.register
def _(action: ModifyAction, connection: ldap3.Connection) -> None:
action.logger.debug(
"Executing %s for %s (%s)",
type(action).__name__,
action.record_dn,
", ".join(action.modifications),
)
connection.modify(
dn=action.record_dn,
changes={
# attention: new_value might be list!
attr: (ldap3.MODIFY_REPLACE, new_value)
for attr, new_value in action.modifications.items()
},
)
debug_whether_success(action.logger, connection)
@execute_real.register
def _(action: DeleteAction, connection: ldap3.Connection) -> None:
action.logger.debug("Executing %s for %s", type(action).__name__, action.record_dn)
connection.delete(action.record_dn)
debug_whether_success(action.logger, connection)
@execute_real.register
def _(action: IdleAction, connection: ldap3.Connection) -> None:
pass
[docs]
def debug_whether_success(logger: logging.Logger, connection: ldap3.Connection) -> None:
"""Communicate whether the last operation on `connection` has been successful."""
if connection.result["result"]:
logger.warning("Operation unsuccessful: %s", connection.result)
else:
logger.debug("Operation successful")