allow to use one application for multiple repositories

This commit is contained in:
2023-08-28 19:24:42 +03:00
parent c915d68c97
commit 32b00de42c
103 changed files with 1229 additions and 599 deletions

View File

@ -27,7 +27,8 @@ def application_packages(configuration: Configuration, database: SQLite, reposit
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
return ApplicationPackages("x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
return ApplicationPackages(repository_id, configuration, report=False)
@pytest.fixture
@ -47,7 +48,8 @@ def application_properties(configuration: Configuration, database: SQLite, repos
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
return ApplicationProperties("x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
return ApplicationProperties(repository_id, configuration, report=False)
@pytest.fixture
@ -67,4 +69,5 @@ def application_repository(configuration: Configuration, database: SQLite, repos
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
return ApplicationRepository("x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
return ApplicationRepository(repository_id, configuration, report=False)

View File

@ -28,7 +28,8 @@ def application(configuration: Configuration, repository: Repository, database:
"""
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
return Application("x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
return Application(repository_id, configuration, report=False)
@pytest.fixture
@ -54,7 +55,8 @@ def lock(args: argparse.Namespace, configuration: Configuration) -> Lock:
Returns:
Lock: file lock test instance
"""
return Lock(args, "x86_64", configuration)
_, repository_id = configuration.check_loaded()
return Lock(args, repository_id, configuration)
@pytest.fixture

View File

@ -19,7 +19,9 @@ from ahriman.models.build_status import BuildStatus, BuildStatusEnum
from ahriman.models.package import Package
from ahriman.models.package_description import PackageDescription
from ahriman.models.package_source import PackageSource
from ahriman.models.pacman_synchronization import PacmanSynchronization
from ahriman.models.remote_source import RemoteSource
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths
from ahriman.models.result import Result
from ahriman.models.user import User
@ -243,18 +245,19 @@ def auth(configuration: Configuration) -> Auth:
@pytest.fixture
def configuration(resource_path_root: Path) -> Configuration:
def configuration(repository_id: RepositoryId, resource_path_root: Path) -> Configuration:
"""
configuration fixture
Args:
repository_id(RepositoryId): repository identifier fixture
resource_path_root(Path): resource path root directory
Returns:
Configuration: configuration test instance
"""
path = resource_path_root / "core" / "ahriman.ini"
return Configuration.from_path(path=path, architecture="x86_64")
return Configuration.from_path(path, repository_id)
@pytest.fixture
@ -434,7 +437,8 @@ def pacman(configuration: Configuration) -> Pacman:
Returns:
Pacman: pacman wrapper test instance
"""
return Pacman("x86_64", configuration, refresh_database=0)
_, repository_id = configuration.check_loaded()
return Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
@pytest.fixture
@ -481,7 +485,19 @@ def repository(configuration: Configuration, database: SQLite, mocker: MockerFix
Repository: repository test instance
"""
mocker.patch("ahriman.core.repository.Repository._set_context")
return Repository.load("x86_64", configuration, database, report=False)
_, repository_id = configuration.check_loaded()
return Repository.load(repository_id, configuration, database, report=False)
@pytest.fixture
def repository_id() -> RepositoryId:
"""
fixture for repository identifier
Returns:
RepositoryId: repository identifier test instance
"""
return RepositoryId("x86_64", "aur-clone")
@pytest.fixture
@ -525,7 +541,12 @@ def spawner(configuration: Configuration) -> Spawn:
Returns:
Spawn: spawner fixture
"""
return Spawn(MagicMock(), "x86_64", ["--architecture", "x86_64", "--configuration", str(configuration.path)])
_, repository_id = configuration.check_loaded()
return Spawn(MagicMock(), repository_id, [
"--architecture", "x86_64",
"--repository", repository_id.name,
"--configuration", str(configuration.path),
])
@pytest.fixture
@ -554,4 +575,5 @@ def watcher(configuration: Configuration, database: SQLite, repository: Reposito
Watcher: package status watcher test instance
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
return Watcher("x86_64", configuration, database)
_, repository_id = configuration.check_loaded()
return Watcher(repository_id, configuration, database)

View File

@ -7,7 +7,7 @@ from pytest_mock import MockerFixture
from systemd.journal import JournalHandler
from ahriman.core.configuration import Configuration
from ahriman.core.log import Log
from ahriman.core.log.log_loader import LogLoader
from ahriman.models.log_handler import LogHandler
@ -15,14 +15,14 @@ def test_handler() -> None:
"""
must extract journald handler if available
"""
assert Log.handler(None) == LogHandler.Journald
assert LogLoader.handler(None) == LogHandler.Journald
def test_handler_selected() -> None:
"""
must return selected log handler
"""
assert Log.handler(LogHandler.Console) == LogHandler.Console
assert LogLoader.handler(LogHandler.Console) == LogHandler.Console
def test_handler_syslog(mocker: MockerFixture) -> None:
@ -31,7 +31,7 @@ def test_handler_syslog(mocker: MockerFixture) -> None:
"""
mocker.patch("pathlib.Path.exists", return_value=True)
mocker.patch.dict(sys.modules, {"systemd.journal": None})
assert Log.handler(None) == LogHandler.Syslog
assert LogLoader.handler(None) == LogHandler.Syslog
def test_handler_console(mocker: MockerFixture) -> None:
@ -40,17 +40,17 @@ def test_handler_console(mocker: MockerFixture) -> None:
"""
mocker.patch("pathlib.Path.exists", return_value=False)
mocker.patch.dict(sys.modules, {"systemd.journal": None})
assert Log.handler(None) == LogHandler.Console
assert LogLoader.handler(None) == LogHandler.Console
def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must load logging
"""
logging_mock = mocker.patch("ahriman.core.log.log.fileConfig", side_effect=fileConfig)
logging_mock = mocker.patch("ahriman.core.log.log_loader.fileConfig", side_effect=fileConfig)
http_log_mock = mocker.patch("ahriman.core.log.http_log_handler.HttpLogHandler.load")
Log.load(configuration, LogHandler.Journald, quiet=False, report=False)
LogLoader.load(configuration, LogHandler.Journald, quiet=False, report=False)
logging_mock.assert_called_once_with(pytest.helpers.anyvar(int), disable_existing_loggers=True)
http_log_mock.assert_called_once_with(configuration, report=False)
assert all(isinstance(handler, JournalHandler) for handler in logging.getLogger().handlers)
@ -60,8 +60,8 @@ def test_load_fallback(configuration: Configuration, mocker: MockerFixture) -> N
"""
must fall back to stderr without errors
"""
mocker.patch("ahriman.core.log.log.fileConfig", side_effect=PermissionError())
Log.load(configuration, LogHandler.Journald, quiet=False, report=False)
mocker.patch("ahriman.core.log.log_loader.fileConfig", side_effect=PermissionError())
LogLoader.load(configuration, LogHandler.Journald, quiet=False, report=False)
def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None:
@ -69,5 +69,5 @@ def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None
must disable logging in case if quiet flag set
"""
disable_mock = mocker.patch("logging.disable")
Log.load(configuration, LogHandler.Journald, quiet=True, report=False)
LogLoader.load(configuration, LogHandler.Journald, quiet=True, report=False)
disable_mock.assert_called_once_with(logging.WARNING)

View File

@ -17,4 +17,5 @@ def remote_call(configuration: Configuration) -> RemoteCall:
"""
configuration.set_option("web", "host", "localhost")
configuration.set_option("web", "port", "8080")
return RemoteCall("x86_64", configuration, "remote-call")
_, repository_id = configuration.check_loaded()
return RemoteCall(repository_id, configuration, "remote-call")

View File

@ -22,7 +22,8 @@ def cleaner(configuration: Configuration, database: SQLite) -> Cleaner:
Returns:
Cleaner: cleaner test instance
"""
return Cleaner("x86_64", configuration, database, report=False,
_, repository_id = configuration.check_loaded()
return Cleaner(repository_id, configuration, database, report=False,
refresh_pacman_database=PacmanSynchronization.Disabled)
@ -43,7 +44,8 @@ def executor(configuration: Configuration, database: SQLite, mocker: MockerFixtu
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_chroot")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_queue")
return Executor("x86_64", configuration, database, report=False,
_, repository_id = configuration.check_loaded()
return Executor(repository_id, configuration, database, report=False,
refresh_pacman_database=PacmanSynchronization.Disabled)
@ -64,5 +66,6 @@ def update_handler(configuration: Configuration, database: SQLite, mocker: Mocke
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_chroot")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_queue")
return UpdateHandler("x86_64", configuration, database, report=False,
_, repository_id = configuration.check_loaded()
return UpdateHandler(repository_id, configuration, database, report=False,
refresh_pacman_database=PacmanSynchronization.Disabled)

View File

@ -15,7 +15,8 @@ def trigger(configuration: Configuration) -> Trigger:
Returns:
Trigger: trigger test instance
"""
return Trigger("x86_64", configuration)
_, repository_id = configuration.check_loaded()
return Trigger(repository_id, configuration)
@pytest.fixture
@ -28,4 +29,5 @@ def trigger_loader(configuration: Configuration) -> TriggerLoader:
Returns:
TriggerLoader: trigger loader test instance
"""
return TriggerLoader.load("x86_64", configuration)
_, repository_id = configuration.check_loaded()
return TriggerLoader.load(repository_id, configuration)

View File

@ -4,33 +4,34 @@ from typing import Any
from unittest.mock import MagicMock
from ahriman.core.configuration import Configuration
from ahriman.core.upload.github import Github
from ahriman.core.upload.github import GitHub
from ahriman.core.upload.remote_service import RemoteService
from ahriman.core.upload.rsync import Rsync
from ahriman.core.upload.s3 import S3
@pytest.fixture
def github(configuration: Configuration) -> Github:
def github(configuration: Configuration) -> GitHub:
"""
fixture for github synchronization
fixture for GitHub synchronization
Args:
configuration(Configuration): configuration fixture
Returns:
Github: github test instance
GitHub: GitHub test instance
"""
return Github("x86_64", configuration, "github:x86_64")
_, repository_id = configuration.check_loaded()
return GitHub(repository_id, configuration, "github:x86_64")
@pytest.fixture
def github_release() -> dict[str, Any]:
"""
fixture for the github release object
fixture for the GitHub release object
Returns:
dict[str, Any]: github test release object
dict[str, Any]: GitHub test release object
"""
return {
"url": "release_url",
@ -59,7 +60,8 @@ def remote_service(configuration: Configuration) -> RemoteService:
"""
configuration.set_option("web", "host", "localhost")
configuration.set_option("web", "port", "8080")
return RemoteService("x86_64", configuration, "remote-service")
_, repository_id = configuration.check_loaded()
return RemoteService(repository_id, configuration, "remote-service")
@pytest.fixture
@ -73,7 +75,8 @@ def rsync(configuration: Configuration) -> Rsync:
Returns:
Rsync: rsync test instance
"""
return Rsync("x86_64", configuration, "rsync")
_, repository_id = configuration.check_loaded()
return Rsync(repository_id, configuration, "rsync")
@pytest.fixture
@ -87,7 +90,8 @@ def s3(configuration: Configuration) -> S3:
Returns:
S3: S3 test instance
"""
return S3("x86_64", configuration, "customs3")
_, repository_id = configuration.check_loaded()
return S3(repository_id, configuration, "customs3")
@pytest.fixture

View File

@ -6,10 +6,10 @@ from pytest_mock import MockerFixture
from typing import Any
from unittest.mock import call as MockCall
from ahriman.core.upload.github import Github
from ahriman.core.upload.github import GitHub
def test_asset_remove(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_asset_remove(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must remove asset from the release
"""
@ -18,7 +18,7 @@ def test_asset_remove(github: Github, github_release: dict[str, Any], mocker: Mo
request_mock.assert_called_once_with("DELETE", "asset_url")
def test_asset_remove_unknown(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_asset_remove_unknown(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must not fail if no asset found
"""
@ -27,7 +27,7 @@ def test_asset_remove_unknown(github: Github, github_release: dict[str, Any], mo
request_mock.assert_not_called()
def test_asset_upload(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_asset_upload(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must upload asset to the repository
"""
@ -42,7 +42,7 @@ def test_asset_upload(github: Github, github_release: dict[str, Any], mocker: Mo
remove_mock.assert_not_called()
def test_asset_upload_with_removal(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_asset_upload_with_removal(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must remove existing file before upload
"""
@ -58,7 +58,7 @@ def test_asset_upload_with_removal(github: Github, github_release: dict[str, Any
])
def test_asset_upload_empty_mimetype(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_asset_upload_empty_mimetype(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must upload asset to the repository with empty mime type if the library cannot guess it
"""
@ -73,7 +73,7 @@ def test_asset_upload_empty_mimetype(github: Github, github_release: dict[str, A
headers={"Content-Type": "application/octet-stream"})
def test_get_local_files(github: Github, resource_path_root: Path, mocker: MockerFixture) -> None:
def test_get_local_files(github: GitHub, resource_path_root: Path, mocker: MockerFixture) -> None:
"""
must get all local files recursively
"""
@ -82,7 +82,7 @@ def test_get_local_files(github: Github, resource_path_root: Path, mocker: Mocke
walk_mock.assert_called()
def test_files_remove(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_files_remove(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must remove files from the remote
"""
@ -91,7 +91,7 @@ def test_files_remove(github: Github, github_release: dict[str, Any], mocker: Mo
remove_mock.assert_called_once_with(github_release, "b")
def test_files_remove_empty(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_files_remove_empty(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must remove nothing if nothing changed
"""
@ -100,7 +100,7 @@ def test_files_remove_empty(github: Github, github_release: dict[str, Any], mock
remove_mock.assert_not_called()
def test_files_upload(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_files_upload(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must upload files to the remote
"""
@ -112,7 +112,7 @@ def test_files_upload(github: Github, github_release: dict[str, Any], mocker: Mo
])
def test_files_upload_empty(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_files_upload_empty(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must upload nothing if nothing changed
"""
@ -121,7 +121,7 @@ def test_files_upload_empty(github: Github, github_release: dict[str, Any], mock
upload_mock.assert_not_called()
def test_release_create(github: Github, mocker: MockerFixture) -> None:
def test_release_create(github: GitHub, mocker: MockerFixture) -> None:
"""
must create release
"""
@ -131,7 +131,7 @@ def test_release_create(github: Github, mocker: MockerFixture) -> None:
json={"tag_name": github.architecture, "name": github.architecture})
def test_release_get(github: Github, mocker: MockerFixture) -> None:
def test_release_get(github: GitHub, mocker: MockerFixture) -> None:
"""
must get release
"""
@ -140,7 +140,7 @@ def test_release_get(github: Github, mocker: MockerFixture) -> None:
request_mock.assert_called_once_with("GET", pytest.helpers.anyvar(str, True))
def test_release_get_empty(github: Github, mocker: MockerFixture) -> None:
def test_release_get_empty(github: GitHub, mocker: MockerFixture) -> None:
"""
must return nothing in case of 404 status code
"""
@ -151,7 +151,7 @@ def test_release_get_empty(github: Github, mocker: MockerFixture) -> None:
assert github.release_get() is None
def test_release_get_exception(github: Github, mocker: MockerFixture) -> None:
def test_release_get_exception(github: GitHub, mocker: MockerFixture) -> None:
"""
must re-raise non HTTPError exception
"""
@ -160,7 +160,7 @@ def test_release_get_exception(github: Github, mocker: MockerFixture) -> None:
github.release_get()
def test_release_get_exception_http_error(github: Github, mocker: MockerFixture) -> None:
def test_release_get_exception_http_error(github: GitHub, mocker: MockerFixture) -> None:
"""
must re-raise HTTPError exception with code differs from 404
"""
@ -170,7 +170,7 @@ def test_release_get_exception_http_error(github: Github, mocker: MockerFixture)
github.release_get()
def test_release_update(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_release_update(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must update release
"""
@ -179,7 +179,7 @@ def test_release_update(github: Github, github_release: dict[str, Any], mocker:
request_mock.assert_called_once_with("POST", "release_url", json={"body": "body"})
def test_release_sync(github: Github, mocker: MockerFixture) -> None:
def test_release_sync(github: GitHub, mocker: MockerFixture) -> None:
"""
must run sync command
"""
@ -199,7 +199,7 @@ def test_release_sync(github: Github, mocker: MockerFixture) -> None:
release_update_mock.assert_called_once_with({}, pytest.helpers.anyvar(int))
def test_release_sync_create_release(github: Github, mocker: MockerFixture) -> None:
def test_release_sync_create_release(github: GitHub, mocker: MockerFixture) -> None:
"""
must create release in case if it does not exist
"""

View File

@ -16,6 +16,7 @@ from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository
from ahriman.core.spawn import Spawn
from ahriman.models.repository_id import RepositoryId
from ahriman.models.user import User
from ahriman.web.web import setup_service
@ -112,7 +113,9 @@ def application(configuration: Configuration, spawner: Spawn, database: SQLite,
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False)
return setup_service("x86_64", configuration, spawner)
_, repository_id = configuration.check_loaded()
return setup_service(repository_id, configuration, spawner)
@pytest.fixture
@ -138,7 +141,8 @@ def application_with_auth(configuration: Configuration, user: User, spawner: Spa
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", True)
application = setup_service("x86_64", configuration, spawner)
_, repository_id = configuration.check_loaded()
application = setup_service(repository_id, configuration, spawner)
generated = user.hash_password(application["validator"].salt)
mocker.patch("ahriman.core.database.SQLite.user_get", return_value=generated)
@ -169,7 +173,9 @@ def application_with_debug(configuration: Configuration, user: User, spawner: Sp
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False)
return setup_service("x86_64", configuration, spawner)
_, repository_id = configuration.check_loaded()
return setup_service(repository_id, configuration, spawner)
@pytest.fixture