Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
jc
pytest
python-ldap
pytest-mh >= 1.0.18
pytest-mh >= 1.0.19
8 changes: 4 additions & 4 deletions sssd_test_framework/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Any, Mapping, Tuple, Type
from typing import Any, Mapping, Self, Tuple, Type

import pytest
from pytest_mh import (
Expand Down Expand Up @@ -99,9 +99,9 @@ def export(self) -> dict:
return d

@classmethod
def _CreateFromArgs(cls, item: pytest.Function, args: Tuple, kwargs: Mapping[str, Any]) -> TopologyMark:
def CreateFromArgs(cls, item: pytest.Function, args: Tuple, kwargs: Mapping[str, Any]) -> Self:
"""
Create :class:`TopologyMark` from pytest marker arguments.
Create :class:`TopologyMark` from pytest.mark.topology arguments.

.. warning::

Expand All @@ -113,7 +113,7 @@ def _CreateFromArgs(cls, item: pytest.Function, args: Tuple, kwargs: Mapping[str
:type item: pytest.Function
:raises ValueError: If the marker is invalid.
:return: Instance of TopologyMark.
:rtype: TopologyMark
:rtype: Self
"""
# First three parameters are positional, the rest are keyword arguments.
if len(args) != 2 and len(args) != 3:
Expand Down
112 changes: 7 additions & 105 deletions sssd_test_framework/hosts/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@

from __future__ import annotations

from abc import ABC, abstractmethod
from pathlib import PurePath
from typing import Any

import ldap
from ldap.ldapobject import ReconnectLDAPObject
from pytest_mh import MultihostHost
from pytest_mh.conn import Powershell
from pytest_mh import MultihostBackupHost, MultihostHost
from pytest_mh.utils.fs import LinuxFileSystem
from pytest_mh.utils.services import SystemdServices

Expand All @@ -18,17 +15,20 @@

__all__ = [
"BaseHost",
"BaseBackupHost",
"BaseDomainHost",
"BaseLDAPDomainHost",
]


class BaseHost(MultihostHost[SSSDMultihostDomain]):
class BaseHost(MultihostBackupHost[SSSDMultihostDomain]):
"""
Base class for all SSSD hosts.
"""

def __init__(self, *args, **kwargs) -> None:
# restore is handled in topology controllers
super().__init__(*args, auto_restore=False, **kwargs)

@property
def features(self) -> dict[str, bool]:
"""
Expand All @@ -37,105 +37,7 @@ def features(self) -> dict[str, bool]:
return {}


class BaseBackupHost(BaseHost, ABC):
"""
Base class for all hosts that supports automatic backup and restore.

A backup of the host is created before starting a test case and all changes
done in the test case to the host are automatically reverted when the test
run is finished.

.. warning::

There might be some limitations on what data can and can not be restored
that depends on particular host. See the documentation of each host
class to learn if a full or partial restoration is done.
"""

def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

self.backup_data: Any | None = None
"""Backup data of vanilla state of this host."""

def pytest_setup(self) -> None:
# Make sure required services are running
try:
self.start()
except NotImplementedError:
pass

# Create backup of initial state
self.backup_data = self.backup()

def pytest_teardown(self) -> None:
self.remove_backup(self.backup_data)

def remove_backup(self, backup_data: Any | None) -> None:
"""
Remove backup data from the host.

:param backup_data: Backup data.
:type backup_data: Any | None
"""
if backup_data is None:
return

if isinstance(backup_data, PurePath):
path = str(backup_data)
else:
raise TypeError(f"Only PurePath is supported as backup_data, got {type(backup_data)}")

if isinstance(self.conn.shell, Powershell):
self.conn.exec(["Remove-Item", "-Force", "-Recurse", path])
else:
self.conn.exec(["rm", "-fr", path])

@abstractmethod
def start(self) -> None:
"""
Start required services.

:raises NotImplementedError: If start operation is not supported.
"""
pass

@abstractmethod
def stop(self) -> None:
"""
Stop required services.

:raises NotImplementedError: If stop operation is not supported.
"""
pass

@abstractmethod
def backup(self) -> Any:
"""
Backup backend data.

Returns directory or file path where the backup is stored (as PurePath)
or any Python data relevant for the backup. This data is passed to
:meth:`restore` which will use this information to restore the host to
its original state.

:return: Backup data.
:rtype: Any
"""
pass

@abstractmethod
def restore(self, backup_data: Any | None) -> None:
"""
Restore backend data.

:param backup_data: Backup data.
:type backup_data: Any | None
"""
pass


class BaseDomainHost(BaseBackupHost):
class BaseDomainHost(BaseHost):
"""
Base class for all domain (backend) hosts.

Expand Down
4 changes: 2 additions & 2 deletions sssd_test_framework/hosts/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@

from pytest_mh.conn import ProcessLogLevel

from .base import BaseBackupHost, BaseLinuxHost
from .base import BaseHost, BaseLinuxHost

__all__ = [
"ClientHost",
]


class ClientHost(BaseBackupHost, BaseLinuxHost):
class ClientHost(BaseHost, BaseLinuxHost):
"""
SSSD client host object.

Expand Down
4 changes: 2 additions & 2 deletions sssd_test_framework/hosts/nfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@

from pytest_mh.conn import ProcessLogLevel

from .base import BaseBackupHost, BaseLinuxHost
from .base import BaseHost, BaseLinuxHost

__all__ = [
"NFSHost",
]


class NFSHost(BaseBackupHost, BaseLinuxHost):
class NFSHost(BaseHost, BaseLinuxHost):
"""
NFS server host object.

Expand Down
Loading