feat: add ability to run build process to remote instances (#118)

This commit is contained in:
2023-12-13 15:38:51 +02:00
committed by GitHub
parent f2f6f6df70
commit 5ddc08fce7
39 changed files with 1062 additions and 73 deletions

View File

@ -197,33 +197,34 @@ def test_update(application_repository: ApplicationRepository, package_ahriman:
paths = [package.filepath for package in package_ahriman.packages.values()]
tree = Tree([Leaf(package_ahriman)])
mocker.patch("ahriman.core.tree.Tree.resolve", return_value=tree.levels())
resolve_mock = mocker.patch("ahriman.application.application.workers.local_updater.LocalUpdater.partition",
return_value=tree.levels())
mocker.patch("ahriman.core.repository.repository.Repository.packages_built", return_value=paths)
build_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_build", return_value=result)
update_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_update", return_value=result)
build_mock = mocker.patch("ahriman.application.application.workers.local_updater.LocalUpdater.update",
return_value=result)
update_mock = mocker.patch("ahriman.core.repository.Repository.process_update", return_value=result)
on_result_mock = mocker.patch(
"ahriman.application.application.application_repository.ApplicationRepository.on_result")
application_repository.update([package_ahriman], Packagers("username"), bump_pkgrel=True)
resolve_mock.assert_called_once_with([package_ahriman])
build_mock.assert_called_once_with([package_ahriman], Packagers("username"), bump_pkgrel=True)
update_mock.assert_has_calls([
MockCall(paths, Packagers("username")),
MockCall(paths, Packagers("username")),
])
update_mock.assert_called_once_with(paths, Packagers("username"))
on_result_mock.assert_has_calls([MockCall(result), MockCall(result)])
def test_update_empty(application_repository: ApplicationRepository, package_ahriman: Package,
def test_update_empty(application_repository: ApplicationRepository, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must skip updating repository if no packages supplied
"""
tree = Tree([Leaf(package_ahriman)])
mocker.patch("ahriman.core.tree.Tree.resolve", return_value=tree.levels())
mocker.patch("ahriman.core.repository.repository.Repository.packages_built", return_value=[])
mocker.patch("ahriman.core.repository.executor.Executor.process_build")
update_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_update")
mocker.patch("ahriman.application.application.workers.Updater.partition", return_value=tree.levels())
mocker.patch("ahriman.core.repository.Repository.packages_built", return_value=[])
mocker.patch("ahriman.application.application.workers.local_updater.LocalUpdater.update", return_value=result)
mocker.patch("ahriman.application.application.application_repository.ApplicationRepository.on_result")
update_mock = mocker.patch("ahriman.core.repository.Repository.process_update")
application_repository.update([package_ahriman])
update_mock.assert_not_called()

View File

@ -0,0 +1,48 @@
import pytest
from ahriman.application.application.workers import Updater
from ahriman.application.application.workers.local_updater import LocalUpdater
from ahriman.application.application.workers.remote_updater import RemoteUpdater
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.worker import Worker
@pytest.fixture
def local_updater(repository: Repository) -> LocalUpdater:
"""
local updater fixture
Args:
repository(Repository): repository fixture
Returns:
LocalUpdater: local updater test instance
"""
return LocalUpdater(repository)
@pytest.fixture
def remote_updater(configuration: Configuration) -> RemoteUpdater:
"""
local updater fixture
Args:
configuration(Configuration): configuration fixture
Returns:
RemoteUpdater: remote updater test instance
"""
_, repository_id = configuration.check_loaded()
return RemoteUpdater([Worker("remote1"), Worker("remote2")], repository_id, configuration)
@pytest.fixture
def updater() -> Updater:
"""
empty updater fixture
Returns:
Updater: empty updater test instance
"""
return Updater()

View File

@ -0,0 +1,30 @@
from pytest_mock import MockerFixture
from ahriman.application.application.workers.local_updater import LocalUpdater
from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result
def test_partition(local_updater: LocalUpdater, mocker: MockerFixture) -> None:
"""
must partition as tree resolution
"""
resolve_mock = mocker.patch("ahriman.core.tree.Tree.resolve")
local_updater.partition([])
resolve_mock.assert_called_once_with([])
def test_update(local_updater: LocalUpdater, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must process package updates
"""
paths = [package.filepath for package in package_ahriman.packages.values()]
mocker.patch("ahriman.core.repository.Repository.packages_built", return_value=paths)
build_mock = mocker.patch("ahriman.core.repository.Repository.process_build", return_value=result)
update_mock = mocker.patch("ahriman.core.repository.Repository.process_update", return_value=result)
assert local_updater.update([package_ahriman], Packagers("username"), bump_pkgrel=True) == result
build_mock.assert_called_once_with([package_ahriman], Packagers("username"), bump_pkgrel=True)
update_mock.assert_called_once_with(paths, Packagers("username"))

View File

@ -0,0 +1,84 @@
from pytest_mock import MockerFixture
from ahriman.application.application.workers.remote_updater import RemoteUpdater
from ahriman.core.http import SyncAhrimanClient
from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result
def test_clients(remote_updater: RemoteUpdater) -> None:
"""
must return map of clients
"""
worker = remote_updater.workers[0]
client = SyncAhrimanClient()
remote_updater._clients.append((worker, client))
assert remote_updater.clients == {worker: client}
def test_update_url(remote_updater: RemoteUpdater) -> None:
"""
must generate update url correctly
"""
worker = remote_updater.workers[0]
assert remote_updater._update_url(worker).startswith(worker.address)
assert remote_updater._update_url(worker).endswith("/api/v1/service/add")
def test_next_worker(remote_updater: RemoteUpdater) -> None:
"""
must return next not used worker
"""
assert remote_updater.next_worker()[0] == remote_updater.workers[0]
assert len(remote_updater.clients) == 1
assert remote_updater.workers[0] in remote_updater.clients
assert remote_updater.next_worker()[0] == remote_updater.workers[1]
assert remote_updater.workers[1] in remote_updater.clients
assert len(remote_updater.clients) == 2
def test_next_worker_cycle(remote_updater: RemoteUpdater) -> None:
"""
must return first used worker if no free workers left
"""
worker1, client1 = remote_updater.next_worker()
worker2, client2 = remote_updater.next_worker()
assert remote_updater.next_worker() == (worker1, client1)
assert remote_updater.next_worker() == (worker2, client2)
assert remote_updater.next_worker() == (worker1, client1)
def test_partition(remote_updater: RemoteUpdater, mocker: MockerFixture) -> None:
"""
must partition as tree partition
"""
resolve_mock = mocker.patch("ahriman.core.tree.Tree.partition")
remote_updater.partition([])
resolve_mock.assert_called_once_with([], count=2)
def test_update(remote_updater: RemoteUpdater, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must process remote package updates
"""
worker, client = remote_updater.next_worker()
worker_mock = mocker.patch("ahriman.application.application.workers.remote_updater.RemoteUpdater.next_worker",
return_value=(worker, client))
request_mock = mocker.patch("ahriman.core.http.SyncAhrimanClient.make_request")
assert remote_updater.update([package_ahriman], Packagers("username"), bump_pkgrel=True) == Result()
worker_mock.assert_called_once_with()
request_mock.assert_called_once_with("POST", remote_updater._update_url(worker),
params=remote_updater.repository_id.query(),
json={
"increment": True,
"packager": "username",
"packages": [package_ahriman.base],
"patches": [],
"refresh": True,
}
)

View File

@ -0,0 +1,50 @@
import pytest
from ahriman.application.application.workers import Updater
from ahriman.application.application.workers.local_updater import LocalUpdater
from ahriman.application.application.workers.remote_updater import RemoteUpdater
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.worker import Worker
def test_load(configuration: Configuration, repository: Repository) -> None:
"""
must load local updater if empty worker list is set
"""
_, repository_id = configuration.check_loaded()
assert isinstance(Updater.load(repository_id, configuration, repository), LocalUpdater)
assert isinstance(Updater.load(repository_id, configuration, repository, []), LocalUpdater)
def test_load_from_option(configuration: Configuration, repository: Repository) -> None:
"""
must load remote updater if nonempty worker list is set
"""
_, repository_id = configuration.check_loaded()
assert isinstance(Updater.load(repository_id, configuration, repository, [Worker("remote")]), RemoteUpdater)
def test_load_from_configuration(configuration: Configuration, repository: Repository) -> None:
"""
must load remote updater from settings
"""
configuration.set_option("build", "workers", "remote")
_, repository_id = configuration.check_loaded()
assert isinstance(Updater.load(repository_id, configuration, repository), RemoteUpdater)
def test_partition(updater: Updater) -> None:
"""
must raise not implemented error for missing partition method
"""
with pytest.raises(NotImplementedError):
updater.partition([])
def test_update(updater: Updater) -> None:
"""
must raise not implemented error for missing update method
"""
with pytest.raises(NotImplementedError):
updater.update([])