Add ability to trigger updates from the web (#31)

* add external process spawner and update test cases

* pass no_report to handlers

* provide service api endpoints

* do not spawn process for single architecture run

* pass no report to handlers

* make _call method of handlers public and also simplify process spawn

* move update under add

* implement actions from web page

* clear logging & improve l&f
This commit is contained in:
2021-09-10 00:33:35 +03:00
committed by GitHub
parent 18de70154e
commit 98eb93c27a
101 changed files with 1417 additions and 295 deletions

View File

@ -6,7 +6,7 @@ from pytest_mock import MockerFixture
from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import MissingArchitecture
from ahriman.core.exceptions import MissingArchitecture, MultipleArchitecture
def test_call(args: argparse.Namespace, mocker: MockerFixture) -> None:
@ -20,7 +20,7 @@ def test_call(args: argparse.Namespace, mocker: MockerFixture) -> None:
enter_mock = mocker.patch("ahriman.application.lock.Lock.__enter__")
exit_mock = mocker.patch("ahriman.application.lock.Lock.__exit__")
assert Handler._call(args, "x86_64")
assert Handler.call(args, "x86_64")
enter_mock.assert_called_once()
exit_mock.assert_called_once()
@ -30,7 +30,7 @@ def test_call_exception(args: argparse.Namespace, mocker: MockerFixture) -> None
must process exception
"""
mocker.patch("ahriman.application.lock.Lock.__enter__", side_effect=Exception())
assert not Handler._call(args, "x86_64")
assert not Handler.call(args, "x86_64")
def test_execute(args: argparse.Namespace, mocker: MockerFixture) -> None:
@ -44,6 +44,29 @@ def test_execute(args: argparse.Namespace, mocker: MockerFixture) -> None:
starmap_mock.assert_called_once()
def test_execute_multiple_not_supported(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must raise an exception if multiple architectures are not supported by the handler
"""
args.architecture = ["i686", "x86_64"]
args.command = "web"
mocker.patch.object(Handler, "ALLOW_MULTI_ARCHITECTURE_RUN", False)
with pytest.raises(MultipleArchitecture):
Handler.execute(args)
def test_execute_single(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must run execution in current process if only one architecture supplied
"""
args.architecture = ["x86_64"]
starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap")
Handler.execute(args)
starmap_mock.assert_not_called()
def test_extract_architectures(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must generate list of available architectures
@ -94,4 +117,4 @@ def test_run(args: argparse.Namespace, configuration: Configuration) -> None:
must raise NotImplemented for missing method
"""
with pytest.raises(NotImplementedError):
Handler.run(args, "x86_64", configuration)
Handler.run(args, "x86_64", configuration, True)

View File

@ -26,7 +26,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
mocker.patch("pathlib.Path.mkdir")
application_mock = mocker.patch("ahriman.application.application.Application.add")
Add.run(args, "x86_64", configuration)
Add.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()
@ -41,6 +41,6 @@ def test_run_with_updates(args: argparse.Namespace, configuration: Configuration
application_mock = mocker.patch("ahriman.application.application.Application.update")
updates_mock = mocker.patch("ahriman.application.application.Application.get_updates")
Add.run(args, "x86_64", configuration)
Add.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()
updates_mock.assert_called_once()

View File

@ -28,5 +28,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
mocker.patch("pathlib.Path.mkdir")
application_mock = mocker.patch("ahriman.application.application.Application.clean")
Clean.run(args, "x86_64", configuration)
Clean.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()

View File

@ -19,7 +19,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
args.username = "user"
args.password = "pa55w0rd"
args.role = UserAccess.Status
args.role = UserAccess.Read
args.as_service = False
return args
@ -34,7 +34,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
create_user = mocker.patch("ahriman.application.handlers.CreateUser.create_user")
get_salt_mock = mocker.patch("ahriman.application.handlers.CreateUser.get_salt")
CreateUser.run(args, "x86_64", configuration)
CreateUser.run(args, "x86_64", configuration, True)
get_auth_configuration_mock.assert_called_once()
create_configuration_mock.assert_called_once()
create_user.assert_called_once()

View File

@ -15,6 +15,6 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
application_mock = mocker.patch("ahriman.core.configuration.Configuration.dump",
return_value=configuration.dump())
Dump.run(args, "x86_64", configuration)
Dump.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()
print_mock.assert_called()

View File

@ -13,6 +13,6 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
create_tree_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.create_tree")
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
Init.run(args, "x86_64", configuration)
Init.run(args, "x86_64", configuration, True)
create_tree_mock.assert_called_once()
init_mock.assert_called_once()

View File

@ -25,5 +25,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
mocker.patch("pathlib.Path.mkdir")
application_mock = mocker.patch("ahriman.core.sign.gpg.GPG.import_key")
KeyImport.run(args, "x86_64", configuration)
KeyImport.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()

View File

@ -26,7 +26,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages")
application_mock = mocker.patch("ahriman.application.application.Application.update")
Rebuild.run(args, "x86_64", configuration)
Rebuild.run(args, "x86_64", configuration, True)
application_packages_mock.assert_called_once()
application_mock.assert_called_once()
@ -44,7 +44,7 @@ def test_run_filter(args: argparse.Namespace, configuration: Configuration,
return_value=[package_ahriman, package_python_schedule])
application_mock = mocker.patch("ahriman.application.application.Application.update")
Rebuild.run(args, "x86_64", configuration)
Rebuild.run(args, "x86_64", configuration, True)
application_mock.assert_called_with([package_ahriman])
@ -60,5 +60,5 @@ def test_run_without_filter(args: argparse.Namespace, configuration: Configurati
return_value=[package_ahriman, package_python_schedule])
application_mock = mocker.patch("ahriman.application.application.Application.update")
Rebuild.run(args, "x86_64", configuration)
Rebuild.run(args, "x86_64", configuration, True)
application_mock.assert_called_with([package_ahriman, package_python_schedule])

View File

@ -24,5 +24,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
mocker.patch("pathlib.Path.mkdir")
application_mock = mocker.patch("ahriman.application.application.Application.remove")
Remove.run(args, "x86_64", configuration)
Remove.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()

View File

@ -26,7 +26,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
application_mock = mocker.patch("ahriman.application.application.Application.unknown")
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
RemoveUnknown.run(args, "x86_64", configuration)
RemoveUnknown.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()
remove_mock.assert_called_once()
@ -44,7 +44,7 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, pac
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
log_fn_mock = mocker.patch("ahriman.application.handlers.remove_unknown.RemoveUnknown.log_fn")
RemoveUnknown.run(args, "x86_64", configuration)
RemoveUnknown.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()
remove_mock.assert_not_called()
log_fn_mock.assert_called_with(package_ahriman)

View File

@ -24,5 +24,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
mocker.patch("pathlib.Path.mkdir")
application_mock = mocker.patch("ahriman.application.application.Application.report")
Report.run(args, "x86_64", configuration)
Report.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()

View File

@ -26,7 +26,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, aur_package
mocker.patch("aur.search", return_value=[aur_package_ahriman])
log_mock = mocker.patch("ahriman.application.handlers.search.Search.log_fn")
Search.run(args, "x86_64", configuration)
Search.run(args, "x86_64", configuration, True)
log_mock.assert_called_once()
@ -38,7 +38,7 @@ def test_run_multiple_search(args: argparse.Namespace, configuration: Configurat
args.search = ["ahriman", "is", "cool"]
search_mock = mocker.patch("aur.search")
Search.run(args, "x86_64", configuration)
Search.run(args, "x86_64", configuration, True)
search_mock.assert_called_with(" ".join(args.search))
@ -51,5 +51,5 @@ def test_log_fn(args: argparse.Namespace, configuration: Configuration, aur_pack
mocker.patch("aur.search", return_value=[aur_package_ahriman])
print_mock = mocker.patch("builtins.print")
Search.run(args, "x86_64", configuration)
Search.run(args, "x86_64", configuration, True)
print_mock.assert_called() # we don't really care about call details tbh

View File

@ -39,7 +39,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
sudo_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.create_sudo_configuration")
executable_mock = mocker.patch("ahriman.application.handlers.setup.Setup.create_executable")
Setup.run(args, "x86_64", configuration)
Setup.run(args, "x86_64", configuration, True)
ahriman_configuration_mock.assert_called_once()
devtools_configuration_mock.assert_called_once()
makepkg_configuration_mock.assert_called_once()

View File

@ -24,5 +24,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
mocker.patch("pathlib.Path.mkdir")
application_mock = mocker.patch("ahriman.application.application.Application.sign")
Sign.run(args, "x86_64", configuration)
Sign.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()

View File

@ -30,7 +30,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, package_ahr
packages_mock = mocker.patch("ahriman.core.status.client.Client.get",
return_value=[(package_ahriman, BuildStatus())])
Status.run(args, "x86_64", configuration)
Status.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()
packages_mock.assert_called_once()
@ -46,5 +46,17 @@ def test_run_with_package_filter(args: argparse.Namespace, configuration: Config
packages_mock = mocker.patch("ahriman.core.status.client.Client.get",
return_value=[(package_ahriman, BuildStatus())])
Status.run(args, "x86_64", configuration)
Status.run(args, "x86_64", configuration, True)
packages_mock.assert_called_once()
def test_imply_with_report(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must create application object with native reporting
"""
args = _default_args(args)
mocker.patch("pathlib.Path.mkdir")
load_mock = mocker.patch("ahriman.core.status.client.Client.load")
Status.run(args, "x86_64", configuration, True)
load_mock.assert_called_once()

View File

@ -28,7 +28,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
mocker.patch("pathlib.Path.mkdir")
update_self_mock = mocker.patch("ahriman.core.status.client.Client.update_self")
StatusUpdate.run(args, "x86_64", configuration)
StatusUpdate.run(args, "x86_64", configuration, True)
update_self_mock.assert_called_once()
@ -42,7 +42,7 @@ def test_run_packages(args: argparse.Namespace, configuration: Configuration, pa
mocker.patch("pathlib.Path.mkdir")
update_mock = mocker.patch("ahriman.core.status.client.Client.update")
StatusUpdate.run(args, "x86_64", configuration)
StatusUpdate.run(args, "x86_64", configuration, True)
update_mock.assert_called_once()
@ -57,5 +57,17 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, pack
mocker.patch("pathlib.Path.mkdir")
update_mock = mocker.patch("ahriman.core.status.client.Client.remove")
StatusUpdate.run(args, "x86_64", configuration)
StatusUpdate.run(args, "x86_64", configuration, True)
update_mock.assert_called_once()
def test_imply_with_report(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must create application object with native reporting
"""
args = _default_args(args)
mocker.patch("pathlib.Path.mkdir")
load_mock = mocker.patch("ahriman.core.status.client.Client.load")
StatusUpdate.run(args, "x86_64", configuration, True)
load_mock.assert_called_once()

View File

@ -24,5 +24,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
mocker.patch("pathlib.Path.mkdir")
application_mock = mocker.patch("ahriman.application.application.Application.sync")
Sync.run(args, "x86_64", configuration)
Sync.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()

View File

@ -30,7 +30,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
application_mock = mocker.patch("ahriman.application.application.Application.update")
updates_mock = mocker.patch("ahriman.application.application.Application.get_updates")
Update.run(args, "x86_64", configuration)
Update.run(args, "x86_64", configuration, True)
application_mock.assert_called_once()
updates_mock.assert_called_once()
@ -44,7 +44,7 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, moc
mocker.patch("pathlib.Path.mkdir")
updates_mock = mocker.patch("ahriman.application.application.Application.get_updates")
Update.run(args, "x86_64", configuration)
Update.run(args, "x86_64", configuration, True)
updates_mock.assert_called_once()

View File

@ -6,14 +6,33 @@ from ahriman.application.handlers import Web
from ahriman.core.configuration import Configuration
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
:param args: command line arguments fixture
:return: generated arguments for these test cases
"""
args.parser = lambda: True
return args
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("pathlib.Path.mkdir")
mocker.patch("ahriman.core.spawn.Spawn.start")
setup_mock = mocker.patch("ahriman.web.web.setup_service")
run_mock = mocker.patch("ahriman.web.web.run_server")
Web.run(args, "x86_64", configuration)
Web.run(args, "x86_64", configuration, True)
setup_mock.assert_called_once()
run_mock.assert_called_once()
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Web.ALLOW_MULTI_ARCHITECTURE_RUN