From 6bd1636bfa7e65f75b4837f2c473fe1d87f298f2 Mon Sep 17 00:00:00 2001 From: Evgenii Alekseev Date: Tue, 17 Oct 2023 03:53:33 +0300 Subject: [PATCH] feat: allow to use single web instance for all repositories (#114) * Allow to use single web instance for any repository * some improvements * drop includes from user home directory, introduce new variables to docker The old solution didn't actually work as expected, because devtools configuration belongs to filesystem (as well as sudo one), so it was still required to run setup command. In order to handle additional repositories, the POSTSETUP and PRESETUP commands variables have been introduced. FAQ has been updated as well * raise 404 in case if repository is unknown --- .github/workflows/setup.sh | 2 +- CONTRIBUTING.md | 1 + Dockerfile | 2 + docker/entrypoint.sh | 3 + docs/ahriman.application.handlers.rst | 8 + docs/ahriman.core.formatters.rst | 8 + docs/ahriman.models.rst | 8 + docs/ahriman.web.schemas.rst | 8 + docs/ahriman.web.views.v1.status.rst | 8 + docs/configuration.rst | 8 +- docs/faq.rst | 24 +- docs/migration.rst | 4 +- docs/setup.rst | 2 +- package/archlinux/PKGBUILD | 2 +- .../lib/systemd/system/ahriman-web.service | 12 + .../lib/systemd/system/ahriman-web@.service | 13 +- .../ahriman/templates/build-status.jinja2 | 31 +- .../build-status/key-import-modal.jinja2 | 34 +-- .../templates/build-status/login-modal.jinja2 | 18 +- .../build-status/package-add-modal.jinja2 | 47 ++- .../build-status/package-info-modal.jinja2 | 8 +- .../build-status/package-rebuild-modal.jinja2 | 26 +- .../templates/build-status/table.jinja2 | 63 +++- .../share/ahriman/templates/static/logo.svg | 70 +++++ .../templates/utils/bootstrap-scripts.jinja2 | 2 +- .../bash-completion/completions/_ahriman | 21 +- package/share/man/man1/ahriman.1 | 35 ++- package/share/zsh/site-functions/_ahriman | 20 +- src/ahriman/application/ahriman.py | 87 ++++-- .../application/application/application.py | 2 +- .../application/application_packages.py | 2 +- .../application/application_repository.py | 2 +- src/ahriman/application/handlers/__init__.py | 1 + src/ahriman/application/handlers/dump.py | 22 +- src/ahriman/application/handlers/handler.py | 110 +++---- .../application/handlers/repositories.py | 54 ++++ src/ahriman/application/handlers/search.py | 7 +- .../application/handlers/service_updates.py | 5 +- src/ahriman/application/handlers/setup.py | 8 +- .../application/handlers/status_update.py | 12 +- src/ahriman/application/handlers/web.py | 24 +- src/ahriman/application/lock.py | 5 +- src/ahriman/core/alpm/remote/aur.py | 8 +- src/ahriman/core/alpm/remote/official.py | 8 +- .../core/alpm/remote/official_syncdb.py | 7 +- src/ahriman/core/alpm/remote/remote.py | 23 +- .../core/configuration/configuration.py | 27 +- src/ahriman/core/configuration/schema.py | 1 - .../database/operations/build_operations.py | 6 +- .../database/operations/logs_operations.py | 27 +- .../core/database/operations/operations.py | 3 +- .../database/operations/package_operations.py | 94 ++++-- src/ahriman/core/formatters/__init__.py | 1 + .../core/formatters/repository_printer.py | 53 ++++ src/ahriman/core/log/http_log_handler.py | 12 +- src/ahriman/core/log/log_loader.py | 7 +- src/ahriman/core/report/remote_call.py | 14 +- .../core/repository/repository_properties.py | 2 +- src/ahriman/core/repository/update_handler.py | 2 +- src/ahriman/core/spawn.py | 73 +++-- src/ahriman/core/status/client.py | 6 +- src/ahriman/core/status/watcher.py | 31 +- src/ahriman/core/status/web_client.py | 24 +- src/ahriman/core/upload/remote_service.py | 5 +- src/ahriman/models/package.py | 7 +- src/ahriman/models/process_status.py | 36 +++ src/ahriman/models/repository_id.py | 21 ++ src/ahriman/web/schemas/__init__.py | 1 + .../web/schemas/internal_status_schema.py | 13 +- src/ahriman/web/schemas/log_schema.py | 5 +- .../web/schemas/package_status_schema.py | 7 + src/ahriman/web/schemas/pagination_schema.py | 6 +- .../web/schemas/repository_id_schema.py | 35 +++ src/ahriman/web/views/base.py | 62 +++- src/ahriman/web/views/index.py | 13 +- src/ahriman/web/views/v1/service/add.py | 7 +- src/ahriman/web/views/v1/service/pgp.py | 10 +- src/ahriman/web/views/v1/service/process.py | 2 +- src/ahriman/web/views/v1/service/rebuild.py | 7 +- src/ahriman/web/views/v1/service/remove.py | 7 +- src/ahriman/web/views/v1/service/request.py | 7 +- src/ahriman/web/views/v1/service/search.py | 2 +- src/ahriman/web/views/v1/service/update.py | 6 +- src/ahriman/web/views/v1/service/upload.py | 11 +- src/ahriman/web/views/v1/status/logs.py | 18 +- src/ahriman/web/views/v1/status/package.py | 22 +- src/ahriman/web/views/v1/status/packages.py | 17 +- .../web/views/v1/status/repositories.py | 65 ++++ src/ahriman/web/views/v1/status/status.py | 16 +- src/ahriman/web/views/v1/user/login.py | 2 +- src/ahriman/web/views/v2/status/logs.py | 11 +- src/ahriman/web/web.py | 27 +- .../application/test_application.py | 4 +- .../application/handlers/test_handler.py | 54 ++-- .../application/handlers/test_handler_dump.py | 46 +++ .../handlers/test_handler_repositories.py | 37 +++ .../handlers/test_handler_search.py | 4 +- .../handlers/test_handler_service_updates.py | 2 +- .../handlers/test_handler_setup.py | 12 +- .../handlers/test_handler_status_update.py | 7 +- .../application/handlers/test_handler_web.py | 28 +- tests/ahriman/application/test_ahriman.py | 289 ++++++++++-------- tests/ahriman/application/test_lock.py | 2 +- tests/ahriman/conftest.py | 15 +- tests/ahriman/core/alpm/remote/test_aur.py | 14 +- .../ahriman/core/alpm/remote/test_official.py | 16 +- .../core/alpm/remote/test_official_syncdb.py | 11 + .../core/configuration/test_configuration.py | 40 ++- .../operations/test_build_operations.py | 12 +- .../operations/test_logs_operations.py | 17 +- .../operations/test_package_operations.py | 52 ++-- tests/ahriman/core/formatters/conftest.py | 16 +- .../formatters/test_repository_printer.py | 15 + .../ahriman/core/log/test_http_log_handler.py | 23 +- tests/ahriman/core/log/test_log_loader.py | 12 +- tests/ahriman/core/report/test_remote_call.py | 12 +- .../core/repository/test_update_handler.py | 2 +- tests/ahriman/core/status/conftest.py | 3 +- tests/ahriman/core/status/test_client.py | 17 +- tests/ahriman/core/status/test_watcher.py | 37 +-- tests/ahriman/core/status/test_web_client.py | 29 +- tests/ahriman/core/test_spawn.py | 98 +++--- tests/ahriman/core/test_util.py | 1 + .../core/upload/test_remote_service.py | 18 +- tests/ahriman/models/test_migration.py | 34 --- tests/ahriman/models/test_migration_result.py | 34 +++ tests/ahriman/models/test_package.py | 5 +- tests/ahriman/models/test_process_status.py | 0 tests/ahriman/models/test_repository_id.py | 23 ++ tests/ahriman/web/conftest.py | 34 +-- .../web/schemas/test_repository_id_schema.py | 1 + tests/ahriman/web/test_web.py | 16 +- tests/ahriman/web/views/test_view_base.py | 63 +++- .../v1/service/test_view_v1_service_add.py | 5 +- .../service/test_view_v1_service_rebuild.py | 5 +- .../v1/service/test_view_v1_service_remove.py | 5 +- .../service/test_view_v1_service_request.py | 5 +- .../v1/service/test_view_v1_service_search.py | 2 +- .../v1/service/test_view_v1_service_update.py | 5 +- .../v1/status/test_view_v1_status_package.py | 29 +- .../test_view_v1_status_repositories.py | 37 +++ 141 files changed, 2037 insertions(+), 917 deletions(-) create mode 100644 package/lib/systemd/system/ahriman-web.service mode change 100644 => 120000 package/lib/systemd/system/ahriman-web@.service create mode 100644 package/share/ahriman/templates/static/logo.svg create mode 100644 src/ahriman/application/handlers/repositories.py create mode 100644 src/ahriman/core/formatters/repository_printer.py create mode 100644 src/ahriman/models/process_status.py create mode 100644 src/ahriman/web/schemas/repository_id_schema.py create mode 100644 src/ahriman/web/views/v1/status/repositories.py create mode 100644 tests/ahriman/application/handlers/test_handler_repositories.py create mode 100644 tests/ahriman/core/formatters/test_repository_printer.py create mode 100644 tests/ahriman/models/test_process_status.py create mode 100644 tests/ahriman/web/schemas/test_repository_id_schema.py create mode 100644 tests/ahriman/web/views/v1/status/test_view_v1_status_repositories.py diff --git a/.github/workflows/setup.sh b/.github/workflows/setup.sh index 0efece74..18e96b56 100755 --- a/.github/workflows/setup.sh +++ b/.github/workflows/setup.sh @@ -42,7 +42,7 @@ ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot ``. * ``AHRIMAN_PACMAN_MIRROR`` - override pacman mirror server if set. * ``AHRIMAN_PORT`` - HTTP server port if any, default is empty. +* ``AHRIMAN_POSTSETUP_COMMAND`` - if set, the command which will be called (as root) after the setup command, but before any other actions. +* ``AHRIMAN_PRESETUP_COMMAND`` - if set, the command which will be called (as root) right before the setup command. * ``AHRIMAN_REPOSITORY`` - repository name, default is ``aur-clone``. * ``AHRIMAN_REPOSITORY_SERVER`` - optional override for the repository url. Useful if you would like to download packages from remote instead of local filesystem. * ``AHRIMAN_REPOSITORY_ROOT`` - repository root. Because of filesystem rights it is required to override default repository root. By default, it uses ``ahriman`` directory inside ahriman's home, which can be passed as mount volume. @@ -429,7 +431,7 @@ This command uses same rules as ``repo-update``, thus, e.g. requires ``--privile Web service setup ^^^^^^^^^^^^^^^^^ -Well for that you would need to have web container instance running forever; it can be achieved by the following command: +For that you would need to have web container instance running forever; it can be achieved by the following command: .. code-block:: shell @@ -451,6 +453,20 @@ Otherwise, you would need to pass ``AHRIMAN_PORT`` and mount container network t docker run --privileged --net=host -e AHRIMAN_PORT=8080 -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest +Mutli-repository web service +"""""""""""""""""""""""""""" + +Idea is pretty same as to just run web service. However, it is required to run setup commands for each repository, except for one which is specified by ``AHRIMAN_REPOSITORY`` and ``AHRIMAN_ARCHITECTURE`` variables. + +In order to create configuration for additional repositories, the ``AHRIMAN_POSTSETUP_COMMAND`` variable should be used, e.g.: + +.. code-block:: shell + + docker run --privileged -p 8080:8080 -e AHRIMAN_PORT=8080 -e AHRIMAN_UNIX_SOCKET=/var/lib/ahriman/ahriman/ahriman-web.sock -e AHRIMAN_POSTSETUP_COMMAND="ahriman --architecture x86_64 --repository aur-clone-v2 service-setup --build-as-user ahriman --packager 'ahriman bot '" -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest + +The command above will also create configuration for the repository named ``aur-clone-v2``. + +Note, however, that the command above is only required in case if the service is going to be used to run subprocesses. Otherwise, everything else (web interface, status, etc) will be handled as usual. Non-x86_64 architecture setup ----------------------------- @@ -1073,7 +1089,7 @@ How to setup web service port = 8080 #. - Start the web service ``systemctl enable --now ahriman-web@x86_64-aur-clone``. + Start the web service ``systemctl enable --now ahriman-web``. How to enable basic authorization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1130,7 +1146,7 @@ How to enable basic authorization sudo -u ahriman ahriman user-add -r full my-first-user #. - Restart web service ``systemctl restart ahriman-web@x86_64-aur-clone``. + Restart web service ``systemctl restart ahriman-web``. How to enable OAuth authorization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1176,7 +1192,7 @@ How to enable OAuth authorization When it will ask for the password leave it blank. #. - Restart web service ``systemctl restart ahriman-web@x86_64-aur-clone``. + Restart web service ``systemctl restart ahriman-web``. How to implement own interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/migration.rst b/docs/migration.rst index 265bf982..0a6ba9c8 100644 --- a/docs/migration.rst +++ b/docs/migration.rst @@ -54,6 +54,8 @@ In order to migrate to new filesystem tree the following actions are required: Alternatively it can be done by running ``service-setup`` command again. +#. If you didn't run setup command on the previous step, make sure to remove architecture reference from ``web`` section (if any). + #. Make sure to update remote synchronization services if any. Almost all of them rely on current repository tree by default, so you need to setup either redirects or configure to synchronize to the old locations (e.g. ``object_path`` option for S3 synchronization). @@ -63,4 +65,4 @@ In order to migrate to new filesystem tree the following actions are required: .. code-block:: shell sudo systemctl enable --now ahriman@x86_64-aur-clone.timer - sudo systemctl enable --now ahriman-web@x86_64-aur-clone + sudo systemctl enable --now ahriman-web diff --git a/docs/setup.rst b/docs/setup.rst index 34227cbd..c431046b 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -81,7 +81,7 @@ Initial setup .. code-block:: shell - systemctl enable --now ahriman-web@x86_64-aur-clone + systemctl enable --now ahriman-web #. Add packages by using ``ahriman package-add {package}`` command: diff --git a/package/archlinux/PKGBUILD b/package/archlinux/PKGBUILD index 44f4156d..5a87f515 100644 --- a/package/archlinux/PKGBUILD +++ b/package/archlinux/PKGBUILD @@ -46,7 +46,7 @@ package() { python -m installer --destdir="$pkgdir" "dist/$pkgname-$pkgver-py3-none-any.whl" # thanks too PEP517, which we all wanted, you need to install data files manually nowadays - pushd package && find . -type f -exec install -Dm644 "{}" "$pkgdir/usr/{}" \; && popd + pushd package && find . \( -type f -or -type l \) -exec install -Dm644 "{}" "$pkgdir/usr/{}" \; && popd # keep usr/share configs as reference and copy them to /etc install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini" diff --git a/package/lib/systemd/system/ahriman-web.service b/package/lib/systemd/system/ahriman-web.service new file mode 100644 index 00000000..eb7693d1 --- /dev/null +++ b/package/lib/systemd/system/ahriman-web.service @@ -0,0 +1,12 @@ +[Unit] +Description=ArcH linux ReposItory MANager web server +After=network.target + +[Service] +Type=simple +ExecStart=/usr/bin/ahriman web +User=ahriman +Group=ahriman + +[Install] +WantedBy=multi-user.target diff --git a/package/lib/systemd/system/ahriman-web@.service b/package/lib/systemd/system/ahriman-web@.service deleted file mode 100644 index 7b137599..00000000 --- a/package/lib/systemd/system/ahriman-web@.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=ArcH linux ReposItory MANager web server (%i) -After=network.target - -[Service] -Type=simple -ExecStart=/usr/bin/ahriman --repository-id "%I" web -User=ahriman -Group=ahriman - -[Install] -WantedBy=multi-user.target diff --git a/package/lib/systemd/system/ahriman-web@.service b/package/lib/systemd/system/ahriman-web@.service new file mode 120000 index 00000000..c0d35a32 --- /dev/null +++ b/package/lib/systemd/system/ahriman-web@.service @@ -0,0 +1 @@ +ahriman-web.service \ No newline at end of file diff --git a/package/share/ahriman/templates/build-status.jinja2 b/package/share/ahriman/templates/build-status.jinja2 index 880db5d9..7fdf0d26 100644 --- a/package/share/ahriman/templates/build-status.jinja2 +++ b/package/share/ahriman/templates/build-status.jinja2 @@ -1,7 +1,7 @@ - {{ repository }} + ahriman @@ -16,7 +16,22 @@ {% include "utils/bootstrap-scripts.jinja2" %}
-

ahriman

+
@@ -31,28 +46,28 @@ - {% endif %} @@ -117,7 +132,7 @@ {% if auth.enabled %}