mirror of
				https://github.com/arcan1s/ahriman.git
				synced 2025-11-04 07:43:42 +00:00 
			
		
		
		
	feat: add ability to run build process to remote instances (#118)
This commit is contained in:
		@ -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()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										48
									
								
								tests/ahriman/application/application/workers/conftest.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								tests/ahriman/application/application/workers/conftest.py
									
									
									
									
									
										Normal 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()
 | 
			
		||||
@ -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"))
 | 
			
		||||
@ -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,
 | 
			
		||||
    }
 | 
			
		||||
    )
 | 
			
		||||
@ -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([])
 | 
			
		||||
		Reference in New Issue
	
	Block a user