From b378a519a66fa34a4479fddc999b9f7cdfb8f25d Mon Sep 17 00:00:00 2001 From: Jens Diemer Date: Tue, 22 Aug 2023 19:52:36 +0200 Subject: [PATCH] Update to manifest v2 Update via https://github.com/jedie/manageprojects and https://github.com/jedie/cookiecutter_templates/ --- .github/workflows/package_linter.yml | 16 +- .gitignore | 5 +- check_process | 33 --- conf/gunicorn.conf.py | 2 +- conf/manage.py | 2 +- conf/nginx.conf | 4 +- conf/requirements.txt | 43 ++-- conf/settings.py | 32 +-- conf/systemd.service | 4 +- conf/urls.py | 2 +- doc/DESCRIPTION.md | 14 +- doc/DISCLAIMER.md | 147 +---------- manifest.json | 47 ---- manifest.toml | 110 +++++++++ poetry.lock | 114 ++++++--- pyproject.toml | 6 +- scripts/_common.sh | 68 ++++-- scripts/backup | 22 +- scripts/change_url | 123 +--------- scripts/install | 228 ++++++------------ scripts/remove | 51 +--- scripts/restore | 106 ++------ scripts/upgrade | 150 ++---------- tests.toml | 31 +++ tests/conftest.py | 18 +- tests/test_django_project.py | 8 +- ...roject_create_unknown_user_1.snapshot.html | 25 +- tests/test_project_setup.py | 41 +++- 28 files changed, 537 insertions(+), 915 deletions(-) delete mode 100644 check_process delete mode 100644 manifest.json create mode 100644 manifest.toml create mode 100644 tests.toml diff --git a/.github/workflows/package_linter.yml b/.github/workflows/package_linter.yml index 8ae9e4e..60156f4 100644 --- a/.github/workflows/package_linter.yml +++ b/.github/workflows/package_linter.yml @@ -15,18 +15,15 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - # https://github.com/marketplace/actions/checkout - with: - fetch-depth: 0 - - uses: actions/cache@v3 - # https://github.com/marketplace/actions/cache + - name: Set up Python + uses: actions/setup-python@v4 with: - path: ~/.cache/ - key: dot-cache-files + python-version: '3.9' - - name: 'Install dependencies' + - name: Install dependencies run: | + python -m pip install --upgrade pip pip install toml - name: 'Clone YunoHost apps package linter' @@ -34,8 +31,7 @@ jobs: git clone --depth=1 https://github.com/YunoHost/package_linter ~/package_linter - name: 'Install requirements' - run: | - pip3 install toml + run: pip3 install toml - name: 'Run linter' run: | diff --git a/.gitignore b/.gitignore index 15c56cd..fc3ddd4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,10 @@ !.gitignore !.gitkeep !/doc/screenshots/.gitkeep + __pycache__ secret.txt /local_test/ -/coverage.json -/coverage.xml + +/coverage.* /htmlcov/ diff --git a/check_process b/check_process deleted file mode 100644 index 670e59f..0000000 --- a/check_process +++ /dev/null @@ -1,33 +0,0 @@ -# See here for more information -# https://github.com/YunoHost/package_check#syntax-check_process-file - -# Move this file from check_process.default to check_process when you have filled it. - -;; Test complet - ; Manifest - domain="domain.tld" (DOMAIN) - path="/path" (PATH) - admin="john" (USER) - is_public=1 (PUBLIC|public=1|private=0) - password="pass" - port="666" (PORT) - ; Checks - pkg_linter=1 - setup_sub_dir=1 - setup_root=1 - setup_nourl=0 - setup_private=0 - setup_public=1 - upgrade=1 - backup_restore=1 - multi_instance=1 - port_already_use=0 - change_url=1 -;;; Options -Email= -Notification=none -;;; Upgrade options - ; commit=CommitHash - name=Name and date of the commit. - manifest_arg=domain=DOMAIN&path=PATH&admin=USER&language=fr&is_public=1&password=pass&port=666& - diff --git a/conf/gunicorn.conf.py b/conf/gunicorn.conf.py index f49a397..cb40c98 100644 --- a/conf/gunicorn.conf.py +++ b/conf/gunicorn.conf.py @@ -17,4 +17,4 @@ accesslog = '__LOG_FILE__' errorlog = '__LOG_FILE__' # https://docs.gunicorn.org/en/latest/settings.html#pidfile -pidfile = '__FINALPATH__/gunicorn.pid' +pidfile = '__DATA_DIR__/gunicorn.pid' # /home/yunohost.app/$app/gunicorn.pid diff --git a/conf/manage.py b/conf/manage.py index ec26808..f8656c0 100755 --- a/conf/manage.py +++ b/conf/manage.py @@ -1,4 +1,4 @@ -#!__FINALPATH__/venv/bin/python +#!__DATA_DIR__/venv/bin/python import os import sys diff --git a/conf/nginx.conf b/conf/nginx.conf index 867d5ef..1577f19 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,8 +1,8 @@ location __PATH__/static/ { # Service static files by nginx - # e.g.: /var/www/$app/static - alias __PUBLIC_PATH__/static/; + # e.g.: /var/www/$app/static/ + alias __INSTALL_DIR__/static/; expires 30d; } diff --git a/conf/requirements.txt b/conf/requirements.txt index eb62032..7ae85a5 100644 --- a/conf/requirements.txt +++ b/conf/requirements.txt @@ -7,9 +7,9 @@ async-timeout==4.0.3 ; python_version >= "3.9" and python_full_version <= "3.11. bleach==6.0.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414 \ --hash=sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4 -bx-django-utils==63 ; python_version >= "3.9" and python_version < "4" \ - --hash=sha256:0023c0c18c8ce21fbee0e3bb563cd0283749495ca22cab1857ac971e4ee2bb05 \ - --hash=sha256:3b050d9d9d4e496e082c29d98d7633eb89ad028c658743b0032ee88e7e49be63 +bx-django-utils==64 ; python_version >= "3.9" and python_version < "4" \ + --hash=sha256:55e920caf2f1fda4f5b199d48558d1e8a8f2408a244833be205e6c4083610906 \ + --hash=sha256:a89c5b6dd13e8ee28b13c315dce28ff5ad0e6637281ef16754cecf32537b5b4f bx-py-utils==85 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:8d6ee4bb0c431304b812f5bebb1bc8e2ab05f1b6c2f8d16d352cbcee5e916cd2 \ --hash=sha256:df023fa05cda8e969d2cbdb4cc348d8b7670567a2fe775faf7a0c869ec56eaa2 @@ -107,7 +107,7 @@ diff-match-patch==20230430 ; python_version >= "3.9" and python_version < "4" \ django-admin-sortable2==2.1.9 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:6de19689cb2f131d256ce19d2fd148728d551943d8463b1d81f6334adfa0b6fc \ --hash=sha256:bf036785c598685a0019eb08340b88fe6ca74bd178033e2290e6c41b62fa4bf1 -django-axes==6.1.0 ; python_version >= "3.9" and python_full_version < "4.0.0" \ +django-axes==6.1.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:a7d509dc76e67440839522a182dc63ecafc3bac3af9de6f263d2bcec1154e50e \ --hash=sha256:e3d44d4ec64ba6d470ef01b6c4b53b6b3747de96821f7c0ef96c64bffa9f6f74 django-ckeditor==6.7.0 ; python_version >= "3.9" and python_version < "4" \ @@ -125,7 +125,7 @@ django-import-export==3.2.0 ; python_version >= "3.9" and python_version < "4" \ django-js-asset==2.1.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:36a3a4dd6e9efc895fb127d13126020f6ec1ec9469ad42878d42143f22495d90 \ --hash=sha256:be6f69ae5c4865617aa7726c48eddb64089a1e7d4ea7d22a35a3beb8282020f6 -django-redis==5.3.0 ; python_version >= "3.9" and python_full_version < "4.0.0" \ +django-redis==5.3.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:2d8660d39f586c41c9907d5395693c477434141690fd7eca9d32376af00b0aac \ --hash=sha256:8bc5793ec06b28ea802aad85ec437e7646511d4e571e07ccad19cfed8b9ddd44 django-reversion-compare==0.16.2 ; python_version >= "3.9" and python_version < "4" \ @@ -140,20 +140,21 @@ django-tagulous==1.3.3 ; python_version >= "3.9" and python_version < "4" \ django-tools==0.54.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:5040a91282be9d1c9d379b0c65da50bcb3691bff03cee54fd4123ace238c3a43 \ --hash=sha256:a7b7bfa5b9c5a81966454d17dffb2403cee25a806c858ee0486a08798227598f -django-yunohost-integration[ynh]==0.5.2 ; python_version >= "3.9" and python_full_version < "4.0.0" \ - --hash=sha256:05d96ae0689eb1b8c7bc30e0d247fddb1c18d2845c17a6e4ca533ed47731a4cb \ - --hash=sha256:6689115f88dc84acaf94dc01ce940023f566bf933f57115563120912a14cbeff -django==4.1.10 ; python_version >= "3.9" and python_version < "4" \ - --hash=sha256:26d0260c2fb8121009e62ffc548b2398dea2522b6454208a852fb0ef264c206c \ - --hash=sha256:56343019a9fd839e2e5bf203daf45f25af79d5bffa4c71d56eae4f4404d82ade +django-yunohost-integration[ynh]==0.6.0 ; python_version >= "3.9" and python_version < "4" \ + --hash=sha256:9596ab56b66edf1b56eccaceb4b5807df237e752128e79568cd13b075267f26f \ + --hash=sha256:dfb72b94ae30e02948dd60ca76d56da4ca6a74ea04f357b8d61b94807fca0493 +django==4.2.4 ; python_version >= "3.9" and python_version < "4" \ + --hash=sha256:7e4225ec065e0f354ccf7349a22d209de09cc1c074832be9eb84c51c1799c432 \ + --hash=sha256:860ae6a138a238fc4f22c99b52f3ead982bb4b1aad8c0122bcd8c8a3a02e409d et-xmlfile==1.1.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c \ --hash=sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada gunicorn==21.2.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0 \ --hash=sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033 -icdiff==2.0.6 ; python_version >= "3.9" and python_version < "4" \ - --hash=sha256:a2673b335d671e64fc73c44e1eaa0aa01fd0e68354e58ee17e863ab29912a79a +icdiff==2.0.7 ; python_version >= "3.9" and python_version < "4" \ + --hash=sha256:f05d1b3623223dd1c70f7848da7d699de3d9a2550b902a8234d9026292fb5762 \ + --hash=sha256:f79a318891adbf59a45e3a7694f5e1f18c5407065264637072ac8363b759866f idna==3.4 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 @@ -227,7 +228,7 @@ pillow==10.0.0 ; python_version >= "3.9" and python_version < "4" \ pprintpp==0.4.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d \ --hash=sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403 -psycopg2==2.9.7 ; python_version >= "3.9" and python_full_version < "4.0.0" \ +psycopg2==2.9.7 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:1a6a2d609bce44f78af4556bea0c62a5e7f05c23e5ea9c599e07678995609084 \ --hash=sha256:44d93a0109dfdf22fe399b419bcd7fa589d86895d3931b01fb321d74dadc68f1 \ --hash=sha256:8275abf628c6dc7ec834ea63f6f3846bf33518907a2b9b693d41fd063767a866 \ @@ -242,9 +243,9 @@ psycopg2==2.9.7 ; python_version >= "3.9" and python_full_version < "4.0.0" \ pyinventory==0.19.2 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:06424c8ddf8521cf5806d834e3aede8254a4960f538a210bfd88508d88fb1d36 \ --hash=sha256:2d92a7f4b4a7b3191819f671e95070b3dd8844fdf2ceb8d971da1e61b094db24 -python-stdnum==1.18 ; python_version >= "3.9" and python_version < "4" \ - --hash=sha256:bcc763d9c49ae23da5d2b7a686d5fd1deec9d9051341160a10d1ac723a26bec0 \ - --hash=sha256:d7f2a3c7ef4635c957b9cbdd9b1993d1f6ee3a2959f03e172c45440d99f296eb +python-stdnum==1.19 ; python_version >= "3.9" and python_version < "4" \ + --hash=sha256:133ec82f56390ea74c190569e98f2fb14b869808b1d54785708f22d0fead8b3f \ + --hash=sha256:1b5b401ad3f45b798b0317313b781a433f5d7a5ff2c9feb8054664f76f78644e pytz==2023.3 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588 \ --hash=sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb @@ -289,15 +290,15 @@ pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f -redis==5.0.0 ; python_version >= "3.9" and python_full_version < "4.0.0" \ +redis==5.0.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:06570d0b2d84d46c21defc550afbaada381af82f5b83e5b3777600e05d8e2ed0 \ --hash=sha256:5cea6c0d335c9a7332a460ed8729ceabb4d0c489c7285b0a86dbbf8a017bd120 requests==2.31.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 -setuptools==68.1.0 ; python_version >= "3.9" and python_full_version < "4.0.0" \ - --hash=sha256:d59c97e7b774979a5ccb96388efc9eb65518004537e85d52e81eaee89ab6dd91 \ - --hash=sha256:e13e1b0bc760e9b0127eda042845999b2f913e12437046e663b833aa96d89715 +setuptools==68.1.2 ; python_version >= "3.9" and python_version < "4" \ + --hash=sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d \ + --hash=sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b six==1.16.0 ; python_version >= "3.9" and python_version < "4" \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 diff --git a/conf/settings.py b/conf/settings.py index 74733f5..635a600 100644 --- a/conf/settings.py +++ b/conf/settings.py @@ -2,7 +2,7 @@ ################################################################################ # Please do not modify this file, it will be reset at the next update. -# You can edit the file __FINALPATH__/local_settings.py and add/modify the settings you need. +# You can edit the file __DATA_DIR__/local_settings.py and add/modify the settings you need. # The parameters you add in local_settings.py will overwrite these, # but you can use the options and documentation in this file to find out what can be done. @@ -22,16 +22,16 @@ from inventory_project.settings.prod import * # noqa:F401,F403 isort:skip from django_yunohost_integration.base_settings import LOGGING # noqa:F401 isort:skip -FINALPATH = __Path('__FINALPATH__') # /opt/yunohost/$app -assert FINALPATH.is_dir(), f'Directory not exists: {FINALPATH}' +DATA_DIR_PATH = __Path('__DATA_DIR__') # /home/yunohost.app/$app/ +assert DATA_DIR_PATH.is_dir(), f'Directory not exists: {DATA_DIR_PATH}' -PUBLIC_PATH = __Path('__PUBLIC_PATH__') # /var/www/$app -assert PUBLIC_PATH.is_dir(), f'Directory not exists: {PUBLIC_PATH}' +INSTALL_DIR_PATH = __Path('__INSTALL_DIR__') # /var/www/$app/ +assert INSTALL_DIR_PATH.is_dir(), f'Directory not exists: {INSTALL_DIR_PATH}' -LOG_FILE = __Path('__LOG_FILE__') # /var/log/$app/pyinventory_ynh.log -assert LOG_FILE.is_file(), f'File not exists: {LOG_FILE}' +LOG_FILE_PATH = __Path('__LOG_FILE__') # /var/log/$app/pyinventory_ynh.log +assert LOG_FILE_PATH.is_file(), f'File not exists: {LOG_FILE_PATH}' -PATH_URL = '__PATH_URL__' # $YNH_APP_ARG_PATH +PATH_URL = '__PATH__' PATH_URL = PATH_URL.strip('/') YNH_CURRENT_HOST = '__YNH_CURRENT_HOST__' # YunoHost main domain from: /etc/yunohost/current_host @@ -40,7 +40,7 @@ YNH_CURRENT_HOST = '__YNH_CURRENT_HOST__' # YunoHost main domain from: /etc/yun # config_panel.toml settings: DEBUG_ENABLED = '__DEBUG_ENABLED__' -DEBUG = bool(int(DEBUG_ENABLED)) +DEBUG = DEBUG_ENABLED == 'YES' LOG_LEVEL = '__LOG_LEVEL__' ADMIN_EMAIL = '__ADMIN_EMAIL__' @@ -52,8 +52,6 @@ DEFAULT_FROM_EMAIL = '__DEFAULT_FROM_EMAIL__' # Function that will be called to finalize a user profile: YNH_SETUP_USER = 'setup_user.setup_project_user' -SECRET_KEY = __get_or_create_secret(FINALPATH / 'secret.txt') # /opt/yunohost/$app/secret.txt - if 'axes' not in INSTALLED_APPS: INSTALLED_APPS.append('axes') # https://github.com/jazzband/django-axes @@ -61,6 +59,9 @@ if 'axes' not in INSTALLED_APPS: INSTALLED_APPS.append('django_yunohost_integration.apps.YunohostIntegrationConfig') +SECRET_KEY = __get_or_create_secret(DATA_DIR_PATH / 'secret.txt') # /home/yunohost.app/$app/secret.txt + + MIDDLEWARE.insert( MIDDLEWARE.index('django.contrib.auth.middleware.AuthenticationMiddleware') + 1, # login a user via HTTP_REMOTE_USER header from SSOwat: @@ -154,8 +155,8 @@ else: STATIC_URL = '/static/' MEDIA_URL = '/media/' -STATIC_ROOT = str(PUBLIC_PATH / 'static') -MEDIA_ROOT = str(PUBLIC_PATH / 'media') +STATIC_ROOT = str(INSTALL_DIR_PATH / 'static') +MEDIA_ROOT = str(INSTALL_DIR_PATH / 'media') # _____________________________________________________________________________ # django-ckeditor @@ -165,16 +166,15 @@ CKEDITOR_BASEPATH = STATIC_URL + 'ckeditor/ckeditor/' # _____________________________________________________________________________ # Django-dbbackup -DBBACKUP_STORAGE_OPTIONS['location'] = str(FINALPATH / 'backups') +DBBACKUP_STORAGE_OPTIONS['location'] = str(DATA_DIR_PATH / 'backups') # ----------------------------------------------------------------------------- # Set log file to e.g.: /var/log/$app/$app.log -LOGGING['handlers']['log_file']['filename'] = str(LOG_FILE) +LOGGING['handlers']['log_file']['filename'] = str(LOG_FILE_PATH) LOGGING['loggers']['inventory'] = { 'handlers': ['syslog', 'log_file', 'mail_admins'], - 'level': 'INFO', 'propagate': False, } for __logger_name in LOGGING['loggers'].keys(): diff --git a/conf/systemd.service b/conf/systemd.service index 6b6cc92..d10d966 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -5,9 +5,9 @@ After=redis.service postgresql.service [Service] User=__APP__ Group=__APP__ -WorkingDirectory=__FINALPATH__/ +WorkingDirectory=__DATA_DIR__/ -ExecStart=__FINALPATH__/venv/bin/gunicorn --config __FINALPATH__/gunicorn.conf.py wsgi +ExecStart=__DATA_DIR__/venv/bin/gunicorn --config __DATA_DIR__/gunicorn.conf.py wsgi StandardOutput=syslog StandardError=syslog diff --git a/conf/urls.py b/conf/urls.py index 68302b4..5c04302 100644 --- a/conf/urls.py +++ b/conf/urls.py @@ -5,7 +5,7 @@ from django.urls import path if settings.PATH_URL: - # settings.PATH_URL is the $YNH_APP_ARG_PATH + # settings.PATH_URL is __PATH__ # Prefix all urls with "PATH_URL": urlpatterns = [ # MEDIA_URL contains the "PATH_URL" already: diff --git a/doc/DESCRIPTION.md b/doc/DESCRIPTION.md index f889519..1ee693f 100644 --- a/doc/DESCRIPTION.md +++ b/doc/DESCRIPTION.md @@ -1,12 +1,14 @@ +[![tests](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/tests.yml) +[![codecov](https://codecov.io/github/jedie/pyinventory_ynh/branch/main/graph/badge.svg)](https://app.codecov.io/github/jedie/pyinventory_ynh) +[![pyinventory_ynh @ PyPi](https://img.shields.io/pypi/v/pyinventory_ynh?label=pyinventory_ynh%20%40%20PyPi)](https://pypi.org/project/pyinventory_ynh/) +[![Python Versions](https://img.shields.io/pypi/pyversions/pyinventory_ynh)](https://github.com/YunoHost-Apps/pyinventory_ynh/blob/main/pyproject.toml) +[![License GPL-3.0-or-later](https://img.shields.io/pypi/l/pyinventory_ynh)](https://github.com/YunoHost-Apps/pyinventory_ynh/blob/main/LICENSE) + [PyInventory](https://github.com/jedie/PyInventory) is a libre web-based management to catalog things including state and location etc. using [Python](https://www.python.org/)/[Django](https://www.djangoproject.com/). -[![Integration level](https://dash.yunohost.org/integration/pyinventory.svg)](https://dash.yunohost.org/appci/app/pyinventory) [![CI Pipeline](https://ci-apps.yunohost.org/ci/badges/pyinventory.status.svg)](https://ci-apps.yunohost.org/ci/apps/pyinventory/) [![Maintain status](https://ci-apps.yunohost.org/ci/badges/pyinventory.maintain.svg)](https://dash.yunohost.org/appci/app/pyinventory) +[![Integration level](https://dash.yunohost.org/integration/pyinventory_ynh.svg)](https://dash.yunohost.org/appci/app/pyinventory_ynh) ![](https://ci-apps.yunohost.org/ci/badges/pyinventory_ynh.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/pyinventory_ynh.maintain.svg) +[![Install pyinventory_ynh with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=pyinventory_ynh) -[![pytest](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/pytest.yml/badge.svg?branch=master)](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/pytest.yml) [![YunoHost apps package linter](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/package_linter.yml/badge.svg)](https://github.com/YunoHost-Apps/pyinventory_ynh/actions/workflows/package_linter.yml) [![Coverage Status on codecov.io](https://codecov.io/gh/YunoHost-Apps/pyinventory_ynh/branch/master/graph/badge.svg)](https://codecov.io/gh/YunoHost-Apps/pyinventory_ynh) - -![pyinventory @ PyPi](https://img.shields.io/pypi/v/pyinventory?label=pyinventory%20%40%20PyPi) -![Python Versions](https://img.shields.io/pypi/pyversions/pyinventory) -![License GPL V3+](https://img.shields.io/pypi/l/pyinventory) Pull requests welcome ;) diff --git a/doc/DISCLAIMER.md b/doc/DISCLAIMER.md index 850e785..75846be 100644 --- a/doc/DISCLAIMER.md +++ b/doc/DISCLAIMER.md @@ -1,152 +1,15 @@ ## Settings and upgrades Almost everything related to PyInventory's configuration is handled in a `"../conf/settings.py"` file. -You can edit the file `/opt/yunohost/pyinventory/local_settings.py` to enable or disable features. +You can edit the file `/home/yunohost.app/django_example/local_settings.py` to enable or disable features. -Test sending emails: +Test sending emails, e.g.: ```bash ssh admin@yourdomain.tld -root@yunohost:~# cd /opt/yunohost/pyinventory/ -root@yunohost:/opt/yunohost/pyinventory# source venv/bin/activate -(venv) root@yunohost:/opt/yunohost/pyinventory# ./manage.py sendtestemail --admins +root@yunohost:~# /home/yunohost.app/pyinventory/manage.py sendtestemail --admins ``` -Background info: Error mails are send to all [settings.ADMINS](https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-ADMINS). By default the YunoHost admin is inserted here. -To check current ADMINS run: +How to debug a django YunoHost app, take a look into: -```bash -(venv) root@yunohost:/opt/yunohost/pyinventory# ./manage.py sendtestemail --admins -``` - -If you prefere to send error emails to a extrnal email address, just do something like this: - -```bash -echo "ADMINS = (('Your Name', 'example@domain.tld'),)" >> /opt/yunohost/pyinventory/local_settings.py -``` - -To check the effective settings, run this: -```bash -(venv) root@yunohost:/opt/yunohost/pyinventory# ./manage.py diffsettings -``` - - -# Miscellaneous - - -## SSO authentication - -[SSOwat](https://github.com/YunoHost/SSOwat) is fully supported via [django-yunohost-integration](https://github.com/YunoHost-Apps/django_yunohost_integration): - -* First user (`$YNH_APP_ARG_ADMIN`) will be created as Django's super user -* All new users will be created as normal users -* Login via SSO is fully supported -* User Email, First / Last name will be updated from SSO data - - -## Links - - * Report a bug about this package: https://github.com/YunoHost-Apps/pyinventory_ynh - * Report a bug about PyInventory itself: https://github.com/jedie/PyInventory - * YunoHost website: https://yunohost.org/ - ---- - -# Developer info - -## package installation / debugging - -Please send your pull request to https://github.com/YunoHost-Apps/pyinventory_ynh - -Try 'main' branch, e.g.: -```bash -sudo yunohost app install https://github.com/YunoHost-Apps/pyinventory_ynh/tree/master --debug -or -sudo yunohost app upgrade pyinventory -u https://github.com/YunoHost-Apps/pyinventory_ynh/tree/master --debug -``` - -Try 'testing' branch, e.g.: -```bash -sudo yunohost app install https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug -or -sudo yunohost app upgrade pyinventory -u https://github.com/YunoHost-Apps/pyinventory_ynh/tree/testing --debug -``` - -To remove call e.g.: -```bash -sudo yunohost app remove pyinventory -``` - -Backup / remove / restore cycle, e.g.: -```bash -yunohost backup create --apps pyinventory -yunohost backup list -archives: - - pyinventory-pre-upgrade1 - - 20201223-163434 -yunohost app remove pyinventory -yunohost backup restore 20201223-163434 --apps pyinventory -``` - -Debug installation, e.g.: -```bash -root@yunohost:~# ls -la /var/www/pyinventory/ -total 18 -drwxr-xr-x 4 root root 4 Dec 8 08:36 . -drwxr-xr-x 6 root root 6 Dec 8 08:36 .. -drwxr-xr-x 2 root root 2 Dec 8 08:36 media -drwxr-xr-x 7 root root 8 Dec 8 08:40 static - -root@yunohost:~# ls -la /opt/yunohost/pyinventory/ -total 58 -drwxr-xr-x 5 pyinventory pyinventory 11 Dec 8 08:39 . -drwxr-xr-x 3 root root 3 Dec 8 08:36 .. --rw-r--r-- 1 pyinventory pyinventory 460 Dec 8 08:39 gunicorn.conf.py --rw-r--r-- 1 pyinventory pyinventory 0 Dec 8 08:39 local_settings.py --rwxr-xr-x 1 pyinventory pyinventory 274 Dec 8 08:39 manage.py --rw-r--r-- 1 pyinventory pyinventory 171 Dec 8 08:39 secret.txt -drwxr-xr-x 6 pyinventory pyinventory 6 Dec 8 08:37 venv --rw-r--r-- 1 pyinventory pyinventory 115 Dec 8 08:39 wsgi.py --rw-r--r-- 1 pyinventory pyinventory 4737 Dec 8 08:39 settings.py - -root@yunohost:~# cd /opt/yunohost/pyinventory/ -root@yunohost:/opt/yunohost/pyinventory# source venv/bin/activate -(venv) root@yunohost:/opt/yunohost/pyinventory# ./manage.py check -PyInventory v0.8.2 (Django v2.2.17) -DJANGO_SETTINGS_MODULE='settings' -PROJECT_PATH:/opt/yunohost/pyinventory/venv/lib/python3.7/site-packages -BASE_PATH:/opt/yunohost/pyinventory -System check identified no issues (0 silenced). - -root@yunohost:~# tail -f /var/log/pyinventory/pyinventory.log -root@yunohost:~# cat /etc/systemd/system/pyinventory.service - -root@yunohost:~# systemctl reload-or-restart pyinventory -root@yunohost:~# journalctl --unit=pyinventory --follow -``` - -## local test - -For quicker developing of PyInventory in the context of YunoHost app, -it's possible to run the Django developer server with the settings -and urls made for YunoHost installation. - -e.g.: -```bash -~$ git clone https://github.com/YunoHost-Apps/pyinventory_ynh.git -~$ cd pyinventory_ynh/ -~/pyinventory_ynh$ make -install-poetry install or update poetry -install install PyInventory via poetry -update update the sources and installation -local-test Run local_test.py to run pyinventory_ynh locally -~/pyinventory_ynh$ make install-poetry -~/pyinventory_ynh$ make install -~/pyinventory_ynh$ make local-test -``` - -Notes: - -* SQlite database will be used -* A super user with username `test` and password `test` is created -* The page is available under `http://127.0.0.1:8000/app_path/` +* https://github.com/YunoHost-Apps/django_example_ynh#developer-info diff --git a/manifest.json b/manifest.json deleted file mode 100644 index 55419f7..0000000 --- a/manifest.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "PyInventory", - "id": "pyinventory", - "packaging_format": 1, - "description": { - "en": "Web based management to catalog things including state and location etc." - }, - "version": "0.19.2~ynh1", - "url": "https://github.com/jedie/PyInventory", - "upstream": { - "license": "GPL-3.0-or-later", - "admindoc": "https://github.com/YunoHost-Apps/pyinventory_ynh", - "userdoc": "https://github.com/jedie/PyInventory", - "code": "https://github.com/jedie/PyInventory" - }, - "license": "GPL-3.0-or-later", - "maintainer": { - "name": "Jens Diemer", - "email": "pyinventory_ynh@jensdiemer.de" - }, - "previous_maintainers": [], - "requirements": { - "yunohost": ">=11" - }, - "multi_instance": true, - "services": [ - "nginx", "postgresql", "redis" - ], - "arguments": { - "install" : [ - { - "name": "domain", - "type": "domain" - }, - { - "name": "path", - "type": "path", - "example": "/pyinventory", - "default": "/pyinventory" - }, - { - "name": "admin", - "type": "user" - } - ] - } -} diff --git a/manifest.toml b/manifest.toml new file mode 100644 index 0000000..b636928 --- /dev/null +++ b/manifest.toml @@ -0,0 +1,110 @@ +# https://yunohost.org/en/packaging_manifest +packaging_format = 2 + +id = "pyinventory" +name = "PyInventory" +description.en = "Web based management to catalog things including state and location etc." + +version = "0.19.2~ynh1" + +maintainers = ["Jens Diemer"] + + +[upstream] +# https://yunohost.org/en/packaging_manifest#upstream-section +license = "GPL-3.0-or-later" +website = "https://github.com/YunoHost-Apps/pyinventory_ynh" +admindoc = "https://github.com/YunoHost-Apps/pyinventory_ynh" +userdoc = "https://github.com/jedie/PyInventory" +code = "https://github.com/YunoHost-Apps/pyinventory_ynh" + + +[integration] +# https://yunohost.org/en/packaging_manifest#integration-section +yunohost = ">=11" +architectures = "all" +multi_instance = true +ldap = true +sso = true +disk = "50M" # **estimate** minimum disk requirement. e.g. 20M, 400M, 1G, ... +ram.build = "50M" # **estimate** minimum ram requirement. e.g. 50M, 400M, 1G, ... +ram.runtime = "50M" # **estimate** minimum ram requirement. e.g. 50M, 400M, 1G, ... + + +[install] + [install.domain] + # this is a generic question - ask strings are automatically handled by Yunohost's core + type = "domain" + + [install.path] + # this is a generic question - ask strings are automatically handled by Yunohost's core + # setting $path and template variable __PATH__ + type = "path" + default = "/pyinventory_ynh" + + [install.admin] + # this is a generic question - ask strings are automatically handled by Yunohost's core + type = "user" + default = "admin" + + [install.init_main_permission] + type = "group" + default = "admins" + + [install.default_from_email] # __DEFAULT_FROM_EMAIL__ + ask.en = "Default email address to use for various automated emails." + type = "email" + example = "admin@example.com" + + [install.admin_email] # __ADMIN_EMAIL__ + ask.en = "EMail address for error emails." + type = "email" + example = "admin@example.com" + + [install.debug_enabled] # __DEBUG_ENABLED__ + ask.en = "Should be never enabled in production!" + type = "select" + choices = ["YES", "NO"] + default = "NO" + + [install.log_level] # __LOG_LEVEL__ + ask.en = "Logging level" + type = "select" + choices = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] + default = "WARNING" + + +[resources] + [resources.system_user] + # This will provision/deprovision a unix system user + + [resources.install_dir] + # https://yunohost.org/en/packaging_apps_resources#install-dir + # This will create/remove the install dir as /var/www/$app/ + # and store the corresponding setting $install_dir and template variable __INSTALL_DIR__ + + [resources.data_dir] + # https://yunohost.org/en/packaging_apps_resources#data-dir + # This will create/remove the data dir as /home/yunohost.app/$app/ + # and store the corresponding setting $data_dir and template variable __DATA_DIR__ + + [resources.permissions] + # https://yunohost.org/en/packaging_apps_resources#permissions + # This will configure SSOwat permission for $domain/$path/ + # The initial allowed group of user is configured via the init_main_permission question (public=visitors, private=all_users) + main.url = "/" + + [resources.ports] + # https://yunohost.org/en/packaging_apps_resources#ports + # This will pick a random port for reverse-proxying and store it as the $port setting + + [resources.apt] + # https://yunohost.org/en/packaging_apps_resources#apt + # This will automatically install/uninstall the following apt packages + packages = "build-essential, python3-dev, python3-pip, python3-venv, git, libpq-dev, postgresql, postgresql-contrib" + + [resources.database] + # https://yunohost.org/en/packaging_apps_resources#database + # This will automatically provision/deprovison a Postgres DB + # and store the corresponding credentials in settings $db_user, $db_name, $db_pwd + type = "postgresql" diff --git a/poetry.lock b/poetry.lock index 63c7497..f64dce8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "asgiref" @@ -123,13 +123,13 @@ css = ["tinycss2 (>=1.1.0,<1.2)"] [[package]] name = "bx-django-utils" -version = "63" +version = "64" description = "Various Django utility functions" optional = false python-versions = ">=3.9,<4.0.0" files = [ - {file = "bx_django_utils-63-py3-none-any.whl", hash = "sha256:0023c0c18c8ce21fbee0e3bb563cd0283749495ca22cab1857ac971e4ee2bb05"}, - {file = "bx_django_utils-63.tar.gz", hash = "sha256:3b050d9d9d4e496e082c29d98d7633eb89ad028c658743b0032ee88e7e49be63"}, + {file = "bx_django_utils-64-py3-none-any.whl", hash = "sha256:55e920caf2f1fda4f5b199d48558d1e8a8f2408a244833be205e6c4083610906"}, + {file = "bx_django_utils-64.tar.gz", hash = "sha256:a89c5b6dd13e8ee28b13c315dce28ff5ad0e6637281ef16754cecf32537b5b4f"}, ] [package.dependencies] @@ -341,6 +341,27 @@ files = [ {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, ] +[[package]] +name = "cli-base-utilities" +version = "0.3.0" +description = "Helpers to bild a CLI program" +optional = false +python-versions = "<4,>=3.9" +files = [ + {file = "cli-base-utilities-0.3.0.tar.gz", hash = "sha256:ca73cf149e5fd10312d450d9919a1ed87222c7bdd6479e94ab670ece4d91e8ba"}, + {file = "cli_base_utilities-0.3.0-py3-none-any.whl", hash = "sha256:1a59a0a61d853b4d3f4944e7494af139bccb3cca4e7766e94f452c2f131a1d59"}, +] + +[package.dependencies] +bx-py-utils = "*" +click = "*" +rich = "*" +rich-click = "*" +tomlkit = "*" + +[package.extras] +dev = ["EditorConfig", "autopep8", "codespell", "coverage", "darker[color,flynt,isort]", "flake8", "manageprojects", "mypy", "pip-tools", "pyflakes", "pyupgrade", "safety", "tomli", "tox", "twine"] + [[package]] name = "click" version = "8.1.7" @@ -558,18 +579,18 @@ files = [ [[package]] name = "django" -version = "4.1.10" +version = "4.2.4" description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." optional = false python-versions = ">=3.8" files = [ - {file = "Django-4.1.10-py3-none-any.whl", hash = "sha256:26d0260c2fb8121009e62ffc548b2398dea2522b6454208a852fb0ef264c206c"}, - {file = "Django-4.1.10.tar.gz", hash = "sha256:56343019a9fd839e2e5bf203daf45f25af79d5bffa4c71d56eae4f4404d82ade"}, + {file = "Django-4.2.4-py3-none-any.whl", hash = "sha256:860ae6a138a238fc4f22c99b52f3ead982bb4b1aad8c0122bcd8c8a3a02e409d"}, + {file = "Django-4.2.4.tar.gz", hash = "sha256:7e4225ec065e0f354ccf7349a22d209de09cc1c074832be9eb84c51c1799c432"}, ] [package.dependencies] -asgiref = ">=3.5.2,<4" -sqlparse = ">=0.2.2" +asgiref = ">=3.6.0,<4" +sqlparse = ">=0.3.1" tzdata = {version = "*", markers = "sys_platform == \"win32\""} [package.extras] @@ -774,18 +795,18 @@ pprintpp = "*" [[package]] name = "django-yunohost-integration" -version = "0.5.2" +version = "0.6.0" description = "Glue code to package django projects as yunohost apps." optional = false -python-versions = ">=3.9,<4.0.0" +python-versions = "<4,>=3.9" files = [ - {file = "django_yunohost_integration-0.5.2-py3-none-any.whl", hash = "sha256:05d96ae0689eb1b8c7bc30e0d247fddb1c18d2845c17a6e4ca533ed47731a4cb"}, - {file = "django_yunohost_integration-0.5.2.tar.gz", hash = "sha256:6689115f88dc84acaf94dc01ce940023f566bf933f57115563120912a14cbeff"}, + {file = "django_yunohost_integration-0.6.0-py3-none-any.whl", hash = "sha256:dfb72b94ae30e02948dd60ca76d56da4ca6a74ea04f357b8d61b94807fca0493"}, + {file = "django_yunohost_integration-0.6.0.tar.gz", hash = "sha256:9596ab56b66edf1b56eccaceb4b5807df237e752128e79568cd13b075267f26f"}, ] [package.dependencies] colorlog = "*" -django = ">=4.0,<4.2" +django = "*" django-axes = {version = "*", optional = true, markers = "extra == \"ynh\""} django-redis = {version = "*", optional = true, markers = "extra == \"ynh\""} django-tools = "*" @@ -795,6 +816,7 @@ psycopg2 = {version = "*", optional = true, markers = "extra == \"ynh\""} pyyaml = "*" [package.extras] +dev = ["EditorConfig", "autopep8", "bx-django-utils", "cli-base-utilities (>=0.3.0)", "click", "codespell", "coverage", "darker[color,flynt,isort]", "django-axes", "django-example", "flake8", "manageprojects (>=0.15.0)", "mypy", "pip-tools", "pyflakes", "pyupgrade", "requests-mock", "rich", "rich-click", "safety", "tomli", "tox", "twine"] ynh = ["django-axes", "django-redis", "gunicorn", "psycopg2"] [[package]] @@ -934,12 +956,13 @@ tornado = ["tornado (>=0.2)"] [[package]] name = "icdiff" -version = "2.0.6" +version = "2.0.7" description = "improved colored diff" optional = false python-versions = "*" files = [ - {file = "icdiff-2.0.6.tar.gz", hash = "sha256:a2673b335d671e64fc73c44e1eaa0aa01fd0e68354e58ee17e863ab29912a79a"}, + {file = "icdiff-2.0.7-py3-none-any.whl", hash = "sha256:f05d1b3623223dd1c70f7848da7d699de3d9a2550b902a8234d9026292fb5762"}, + {file = "icdiff-2.0.7.tar.gz", hash = "sha256:f79a318891adbf59a45e3a7694f5e1f18c5407065264637072ac8363b759866f"}, ] [[package]] @@ -1436,7 +1459,7 @@ files = [ plugins = ["importlib-metadata"] [[package]] -name = "PyInventory" +name = "pyinventory" version = "0.19.2" description = "Web based management to catalog things including state and location etc. using Python/Django." optional = false @@ -1559,13 +1582,13 @@ docutils = "*" [[package]] name = "python-stdnum" -version = "1.18" +version = "1.19" description = "Python module to handle standardized numbers and codes" optional = false python-versions = "*" files = [ - {file = "python-stdnum-1.18.tar.gz", hash = "sha256:bcc763d9c49ae23da5d2b7a686d5fd1deec9d9051341160a10d1ac723a26bec0"}, - {file = "python_stdnum-1.18-py2.py3-none-any.whl", hash = "sha256:d7f2a3c7ef4635c957b9cbdd9b1993d1f6ee3a2959f03e172c45440d99f296eb"}, + {file = "python-stdnum-1.19.tar.gz", hash = "sha256:133ec82f56390ea74c190569e98f2fb14b869808b1d54785708f22d0fead8b3f"}, + {file = "python_stdnum-1.19-py2.py3-none-any.whl", hash = "sha256:1b5b401ad3f45b798b0317313b781a433f5d7a5ff2c9feb8054664f76f78644e"}, ] [package.extras] @@ -1646,13 +1669,13 @@ files = [ [[package]] name = "readme-renderer" -version = "40.0" +version = "41.0" description = "readme_renderer is a library for rendering \"readme\" descriptions for Warehouse" optional = false python-versions = ">=3.8" files = [ - {file = "readme_renderer-40.0-py3-none-any.whl", hash = "sha256:e18feb2a1e7706f2865b81ebb460056d93fb29d69daa10b223c00faa7bd9a00a"}, - {file = "readme_renderer-40.0.tar.gz", hash = "sha256:9f77b519d96d03d7d7dce44977ba543090a14397c4f60de5b6eb5b8048110aa4"}, + {file = "readme_renderer-41.0-py3-none-any.whl", hash = "sha256:a38243d5b6741b700a850026e62da4bd739edc7422071e95fd5c4bb60171df86"}, + {file = "readme_renderer-41.0.tar.gz", hash = "sha256:4f4b11e5893f5a5d725f592c5a343e0dc74f5f273cb3dcf8c42d9703a27073f7"}, ] [package.dependencies] @@ -1748,6 +1771,24 @@ pygments = ">=2.13.0,<3.0.0" [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] +[[package]] +name = "rich-click" +version = "1.6.1" +description = "Format click help output nicely with rich" +optional = false +python-versions = ">=3.7" +files = [ + {file = "rich-click-1.6.1.tar.gz", hash = "sha256:f8ff96693ec6e261d1544e9f7d9a5811c5ef5d74c8adb4978430fc0dac16777e"}, + {file = "rich_click-1.6.1-py3-none-any.whl", hash = "sha256:0fcf4d1a09029d79322dd814ab0b2e66ac183633037561881d45abae8a161d95"}, +] + +[package.dependencies] +click = ">=7" +rich = ">=10.7.0" + +[package.extras] +dev = ["pre-commit"] + [[package]] name = "ruamel-yaml" version = "0.17.32" @@ -1852,17 +1893,17 @@ jeepney = ">=0.6" [[package]] name = "setuptools" -version = "68.1.0" +version = "68.1.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-68.1.0-py3-none-any.whl", hash = "sha256:e13e1b0bc760e9b0127eda042845999b2f913e12437046e663b833aa96d89715"}, - {file = "setuptools-68.1.0.tar.gz", hash = "sha256:d59c97e7b774979a5ccb96388efc9eb65518004537e85d52e81eaee89ab6dd91"}, + {file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"}, + {file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] @@ -1955,15 +1996,26 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tomlkit" +version = "0.12.1" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, + {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, +] + [[package]] name = "tox" -version = "4.9.0" +version = "4.10.0" description = "tox is a generic virtualenv management and test command line tool" optional = false python-versions = ">=3.8" files = [ - {file = "tox-4.9.0-py3-none-any.whl", hash = "sha256:c80de60fe26f9a009b0a763888bf2099ccfbef50a0279a6b9f6de40eb4eb7457"}, - {file = "tox-4.9.0.tar.gz", hash = "sha256:9b6d38fe422599d084afd89375b4803f4bc1f8f16573c77c8fd8ffcc6938f1ff"}, + {file = "tox-4.10.0-py3-none-any.whl", hash = "sha256:e4a1b1438955a6da548d69a52350054350cf6a126658c20943261c48ed6d4c92"}, + {file = "tox-4.10.0.tar.gz", hash = "sha256:e041b2165375be690aca0ec4d96360c6906451380520e4665bf274f66112be35"}, ] [package.dependencies] @@ -2119,4 +2171,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0.0" -content-hash = "43f613d6bcfd86b1152c1425f8f0a6f374a25d53fe692c37131ec419b17239d0" +content-hash = "5635f3ba15d2751757dac50dd8f4e110c38cc04ed9ede20c4f059cfa29d1f5c1" diff --git a/pyproject.toml b/pyproject.toml index 0c4bf13..f1767e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,10 +17,11 @@ pyinventory = ">=0.19.2" # https://github.com/jedie/PyInventory # # extras "ynh" will install: gunicorn, psycopg2, django-redis and django-axes # see: https://github.com/YunoHost-Apps/django_yunohost_integration/blob/main/pyproject.toml -django_yunohost_integration = {version = ">=0.5.1", extras = ["ynh"]} # https://github.com/YunoHost-Apps/django_yunohost_integration +django_yunohost_integration = {version = ">=0.6.0", extras = ["ynh"]} # https://github.com/YunoHost-Apps/django_yunohost_integration [tool.poetry.dev-dependencies] +cli-base-utilities = "*" # https://github.com/jedie/cli-base-utilities bx_py_utils = "*" # https://github.com/boxine/bx_py_utils bx_django_utils = "*" # https://github.com/boxine/bx_django_utils tox = ">=4.4.4" # https://github.com/tox-dev/tox @@ -160,11 +161,12 @@ upstream_url = "https://github.com/jedie/PyInventory" ynh_app_pkg_name = "pyinventory_ynh" ynh_app_url = "https://github.com/YunoHost-Apps/pyinventory_ynh" bug_tracker_url = "https://github.com/jedie/PyInventory/issues" -upstream_version = "0.17.0" +upstream_version = "0.19.2" ynh_version = "1" package_description = "Web based management to catalog things including state and location etc." license = "GPL-3.0-or-later" _template = "https://github.com/jedie/cookiecutter_templates/" applied_migrations = [ "877e2ec", # 2023-08-17T20:54:24+02:00 + "be3f649", # 2023-08-22T19:36:57+02:00 ] diff --git a/scripts/_common.sh b/scripts/_common.sh index 9974cff..f3536db 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -4,15 +4,6 @@ # RETRIEVE ARGUMENTS FROM THE MANIFEST #================================================= -domain=$YNH_APP_ARG_DOMAIN -path_url=$YNH_APP_ARG_PATH - -admin=$YNH_APP_ARG_ADMIN - -# Currently not used: PyInventory has no public pages, yet! -is_public=$YNH_APP_ARG_IS_PUBLIC -app=$YNH_APP_INSTANCE_NAME - # Transfer the main SSO domain to the App: ynh_current_host=$(cat /etc/yunohost/current_host) __YNH_CURRENT_HOST__=${ynh_current_host} @@ -22,7 +13,7 @@ __YNH_CURRENT_HOST__=${ynh_current_host} #================================================= # 'debug_enabled' -> '__DEBUG_ENABLED__' -> settings.DEBUG -debug_enabled="0" +debug_enabled="NO" # "YES" or "NO" string # 'log_level' -> '__LOG_LEVEL__' -> settings.LOG_LEVEL log_level="WARNING" @@ -37,23 +28,62 @@ default_from_email="${app}@${domain}" # SET CONSTANTS #================================================= -public_path=/var/www/$app -final_path=/opt/yunohost/$app +# e.g.: point pip cache to: /home/yunohost.app/$app/.cache/ +XDG_CACHE_HOME="$data_dir/.cache/" + log_path=/var/log/$app log_file="${log_path}/${app}.log" #================================================= -# COMMON VARIABLES +# HELPERS #================================================= -# Needed base dependencies: -pkg_dependencies="build-essential python3-dev python3-pip python3-venv git" +myynh_setup_python_venv() { + # Always recreate everything fresh with current python version + ynh_secure_remove "$data_dir/venv" -# Postgres and Python's "psycopg2": -pkg_dependencies="${pkg_dependencies} libpq-dev postgresql postgresql-contrib" + # Skip pip because of: https://github.com/YunoHost/issues/issues/1960 + python3 -m venv --without-pip "$data_dir/venv" -# dependencies used by the app -pkg_dependencies="${pkg_dependencies} libjpeg-dev" + chown -c -R "$app:" "$data_dir" + + # run source in a 'sub shell' + ( + set +o nounset + source "$data_dir/venv/bin/activate" + set -o nounset + set -x + ynh_exec_as $app $data_dir/venv/bin/python3 -m ensurepip + ynh_exec_as $app $data_dir/venv/bin/pip3 install --upgrade wheel pip setuptools + ynh_exec_as $app $data_dir/venv/bin/pip3 install --no-deps -r "$data_dir/requirements.txt" + ) +} + +myynh_setup_log_file() { + ( + set -x + + mkdir -p "$(dirname "$log_file")" + touch "$log_file" + + chown -c -R $app:$app "$log_path" + chmod -c o-rwx "$log_path" + ) +} + +myynh_fix_file_permissions() { + ( + set -x + + # /var/www/$app/ + chown -c -R "$app:www-data" "$install_dir" + chmod -c o-rwx "$install_dir" + + # /home/yunohost.app/$app/ + chown -c -R "$app:" "$data_dir" + chmod -c o-rwx "$data_dir" + ) +} #================================================= # Redis HELPERS diff --git a/scripts/backup b/scripts/backup index 308ba1c..97a5793 100755 --- a/scripts/backup +++ b/scripts/backup @@ -9,21 +9,6 @@ source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -ynh_abort_if_errors - -#================================================= -# LOAD SETTINGS -#================================================= -ynh_print_info --message="Loading installation settings..." - -app=$YNH_APP_INSTANCE_NAME - -public_path=$(ynh_app_setting_get --app="$app" --key=public_path) -final_path=$(ynh_app_setting_get --app="$app" --key=final_path) -db_name=$(ynh_app_setting_get --app="$app" --key=db_name) - -domain=$(ynh_app_setting_get --app="$app" --key=domain) - #================================================= # DECLARE DATA AND CONF FILES TO BACKUP #================================================= @@ -33,8 +18,11 @@ ynh_print_info --message="Declaring files to be backed up..." # BACKUP THE APP MAIN DIR #================================================= -ynh_backup --src_path="$final_path" -ynh_backup --src_path="$public_path" +# /var/www/$app/ +ynh_backup --src_path="$install_dir" + +# /home/yunohost.app/$app/ +ynh_backup --src_path="$data_dir" #================================================= # BACKUP THE NGINX CONFIGURATION diff --git a/scripts/change_url b/scripts/change_url index cb77f04..b0f3603 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -6,81 +6,9 @@ # IMPORT GENERIC HELPERS #================================================= -YNH_APP_ARG_DOMAIN=$YNH_APP_NEW_DOMAIN -YNH_APP_ARG_PATH=$YNH_APP_NEW_PATH - source _common.sh source /usr/share/yunohost/helpers -#================================================= -# RETRIEVE ARGUMENTS -#================================================= - -old_domain=$YNH_APP_OLD_DOMAIN -old_path=$YNH_APP_OLD_PATH - -new_domain=$YNH_APP_NEW_DOMAIN -new_path=$YNH_APP_NEW_PATH - -#================================================= -# LOAD SETTINGS -#================================================= -ynh_script_progression --message="Loading installation settings..." - -admin=$(ynh_app_setting_get --app="$app" --key=admin) -public_path=$(ynh_app_setting_get --app="$app" --key=public_path) -final_path=$(ynh_app_setting_get --app="$app" --key=final_path) -log_path=$(ynh_app_setting_get --app="$app" --key=log_path) - -port=$(ynh_app_setting_get --app="$app" --key=port) - -db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd) -db_name=$(ynh_sanitize_dbid --db_name="$app") -db_user=$db_name - -redis_db=$(ynh_app_setting_get --app="$app" --key=redis_db) - -#------------------------------------------------- -# config_panel.toml settings: - -debug_enabled=$(ynh_app_setting_get --app="$app" --key=debug_enabled) -log_level=$(ynh_app_setting_get --app="$app" --key=log_level) -admin_email=$(ynh_app_setting_get --app="$app" --key=admin_email) -default_from_email=$(ynh_app_setting_get --app="$app" --key=default_from_email) - -#================================================= -# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP -#================================================= -ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." --weight=40 - -# Backup the current version of the app -ynh_backup_before_upgrade -ynh_clean_setup () { - # Remove the new domain config file, the remove script won't do it as it doesn't know yet its location. - ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" - - # restore it if the upgrade fails - ynh_restore_upgradebackup -} -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors - -#================================================= -# CHECK WHICH PARTS SHOULD BE CHANGED -#================================================= - -change_domain=0 -if [ "$old_domain" != "$new_domain" ] -then - change_domain=1 -fi - -change_path=0 -if [ "$old_path" != "$new_path" ] -then - change_path=1 -fi - #================================================= # STANDARD MODIFICATIONS #================================================= @@ -88,66 +16,31 @@ fi #================================================= ynh_script_progression --message="Stopping systemd service '$app'..." -ynh_systemd_action --service_name="$app" --action="stop" +ynh_systemd_action --service_name=$app --action="stop" --log_path="$log_file" -#================================================= -# STANDARD MODIFICATIONS #================================================= # MODIFY URL IN NGINX CONF #================================================= ynh_script_progression --message="Updating nginx web server configuration..." -nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf - -# Change the path in the nginx config file -if [ $change_path -eq 1 ] -then - # Make a backup of the original nginx config file if modified - ynh_backup_if_checksum_is_different --file="$nginx_conf_path" - # Set global variables for nginx helper - domain="$old_domain" - path_url="$new_path" - # Create a dedicated nginx config - ynh_add_nginx_config "public_path" "port" -fi - -# Change the domain for nginx -if [ $change_domain -eq 1 ] -then - # Delete file checksum for the old conf file location - ynh_delete_file_checksum --file="$nginx_conf_path" - mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf - # Store file checksum for the new config file location - ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" -fi +ynh_change_url_nginx_config #================================================= -# SPECIFIC MODIFICATIONS +# UPDATE DJANGO SETTINGS #================================================= -# MODIFY SETTINGS -#================================================= -ynh_script_progression --message="Modify $app config file..." +ynh_script_progression --message="Update $app settings file..." --weight=1 -domain=$YNH_APP_NEW_DOMAIN -path_url=$YNH_APP_NEW_PATH +path=$new_path +domain=$new_domain -ynh_add_config --template="settings.py" --destination="$final_path/settings.py" +ynh_add_config --template="settings.py" --destination="$data_dir/settings.py" -#================================================= -# GENERIC FINALISATION #================================================= # START SYSTEMD SERVICE #================================================= ynh_script_progression --message="Starting systemd service '$app'..." --weight=5 -ynh_systemd_action --service_name="$app" --action="start" - -#================================================= -# RELOAD NGINX -#================================================= -ynh_script_progression --message="Reloading nginx web server..." - -ynh_systemd_action --service_name=nginx --action=reload +ynh_systemd_action --service_name=$app --action="start" --log_path="$log_file" #================================================= # END OF SCRIPT diff --git a/scripts/install b/scripts/install index b56bb3b..ebbd375 100755 --- a/scripts/install +++ b/scripts/install @@ -7,159 +7,93 @@ source _common.sh source /usr/share/yunohost/helpers -#================================================= -# MANAGE SCRIPT FAILURE -#================================================= +# Install parameters are automatically saved as settings +# +# Settings are automatically loaded as bash variables +# in every app script context, therefore typically these will exist: +# - $domain +# - $path +# - $language +# ... etc +# +# Resources defined in the manifest are provisioned prior to this script +# and corresponding settings are also available, such as: +# - $install_dir +# - $port +# - $db_name +# ... -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors +# +# $app is the app id (i.e. 'example' for first install, +# or 'example__2', '__3', ... for multi-instance installs) +# + +#================================================= +# SETTINGS +#================================================= +ynh_script_progression --message="Storing installation settings..." + +# Logging: +log_file="/var/log/$app/$app.log" +ynh_app_setting_set --app=$app --key=log_file --value="$log_file" + +# Redis: +redis_db=$(ynh_redis_get_free_db) +ynh_app_setting_set --app=$app --key=redis_db --value="$redis_db" + +# App settings: +ynh_app_setting_set --app=$app --key=default_from_email --value="$default_from_email" +ynh_app_setting_set --app=$app --key=admin_email --value="$admin_email" +ynh_app_setting_set --app=$app --key=debug_enabled --value="$debug_enabled" +ynh_app_setting_set --app=$app --key=log_level --value="$log_level" #================================================= # CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS #================================================= ynh_script_progression --message="Validating installation parameters..." -# Path for e.g. "static" files, served by nginx: -test ! -e "$public_path" || ynh_die --message="This path already contains a folder" - -# Path for own config files, e.g.: Django's settings.py: -test ! -e "$final_path" || ynh_die --message="This path already contains a folder" - -# Register (book) web path -ynh_webpath_register --app="$app" --domain="$domain" --path_url="$path_url" - -mkdir -p "$public_path/media" "$public_path/static" -mkdir -p "$final_path" - -mkdir -p "$log_path" -touch "${log_file}" +mkdir -p "$install_dir/media" "$install_dir/static" #================================================= -# STORE SETTINGS FROM MANIFEST +# SETUP LOG FILE #================================================= -ynh_script_progression --message="Storing installation settings..." +ynh_script_progression --message="Setup logging..." -ynh_app_setting_set --app="$app" --key=admin --value="$admin" -ynh_app_setting_set --app="$app" --key=public_path --value="$public_path" -ynh_app_setting_set --app="$app" --key=final_path --value="$final_path" -ynh_app_setting_set --app="$app" --key=log_path --value="$log_file" +myynh_setup_log_file -ynh_app_setting_set --app="$app" --key=domain --value="$domain" -ynh_app_setting_set --app="$app" --key=path --value="$path_url" - -# Find a free port -port=$(ynh_find_port --port=8000) -# Set port as application setting -# https://yunohost.org/en/contribute/packaging_apps/helpers -# https://github.com/YunoHost/yunohost/blob/dev/helpers/setting -ynh_app_setting_set --app="$app" --key=port --value="$port" - -db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd) - -redis_db=$(ynh_redis_get_free_db) -ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db" - -#------------------------------------------------- -# config_panel.toml settings: - -ynh_app_setting_set --app="$app" --key=debug_enabled --value="$debug_enabled" -ynh_app_setting_set --app="$app" --key=log_level --value="$log_level" -ynh_app_setting_set --app="$app" --key=admin_email --value="$admin_email" -ynh_app_setting_set --app="$app" --key=default_from_email --value="$default_from_email" - -#================================================= -# STANDARD MODIFICATIONS -#================================================= -# INSTALL DEPENDENCIES -#================================================= -ynh_script_progression --message="Installing $app dependencies..." --weight=20 - -ynh_exec_warn_less ynh_install_app_dependencies "$pkg_dependencies" - -#================================================= -# CREATE A PostgreSQL DATABASE -#================================================= -ynh_script_progression --message="Creating a PostgreSQL database..." - -db_name=$(ynh_sanitize_dbid --db_name="$app") -db_user=$db_name -ynh_app_setting_set --app="$app" --key=db_name --value="$db_name" - -ynh_psql_test_if_first_run - -# Initialize database and store postgres password for upgrade -ynh_psql_setup_db --db_user="$db_user" --db_name="$db_name" - -#================================================= -# NGINX CONFIGURATION -#================================================= -ynh_script_progression --message="Configuring nginx web server..." - -# Create a dedicated nginx config -# https://yunohost.org/en/contribute/packaging_apps/helpers -# https://github.com/YunoHost/yunohost/blob/dev/helpers/nginx -ynh_add_nginx_config "public_path" "port" - -#================================================= -# CREATE DEDICATED USER -#================================================= -ynh_script_progression --message="Configuring system user '$app'..." - -# A home directory for venv and settings etc. -ynh_system_user_create --username="$app" --home_dir="$final_path" --use_shell +# Use logrotate to manage application logfile(s) +ynh_use_logrotate --logfile="$log_file" --specific_user=$app #================================================= # PYTHON VIRTUALENV #================================================= -ynh_script_progression --message="Create Python virtualenv..." --weight=5 - -# Always recreate everything fresh with current python version -ynh_secure_remove "${final_path}/venv" - -# Skip pip because of: https://github.com/YunoHost/issues/issues/1960 -python3 -m venv --without-pip "${final_path}/venv" - -cp ../conf/requirements.txt "$final_path/requirements.txt" -chown -R "$app:" "$final_path" - -#================================================= -# PIP INSTALLATION -#================================================= -ynh_script_progression --message="Install project via pip..." --weight=45 - -#run source in a 'sub shell' -( - set +o nounset - source "${final_path}/venv/bin/activate" - set -o nounset - ynh_exec_as $app $final_path/venv/bin/python3 -m ensurepip - ynh_exec_as $app $final_path/venv/bin/pip3 install --upgrade wheel pip setuptools - ynh_exec_as $app $final_path/venv/bin/pip3 install --no-deps -r "$final_path/requirements.txt" -) +ynh_script_progression --message="Create and setup Python virtualenv..." --weight=45 +cp ../conf/requirements.txt "$data_dir/requirements.txt" +myynh_setup_python_venv #================================================= # copy config files # ================================================ ynh_script_progression --message="Create $app configuration files..." -ynh_add_config --template="gunicorn.conf.py" --destination="$final_path/gunicorn.conf.py" +ynh_add_config --template="gunicorn.conf.py" --destination="$data_dir/gunicorn.conf.py" -ynh_add_config --template="manage.py" --destination="$final_path/manage.py" -chmod +x "$final_path/manage.py" +ynh_add_config --template="manage.py" --destination="$data_dir/manage.py" +chmod -c +x "$data_dir/manage.py" -ynh_add_config --template="settings.py" --destination="$final_path/settings.py" -ynh_add_config --template="setup_user.py" --destination="$final_path/setup_user.py" -ynh_add_config --template="urls.py" --destination="$final_path/urls.py" -ynh_add_config --template="wsgi.py" --destination="$final_path/wsgi.py" +ynh_add_config --template="settings.py" --destination="$data_dir/settings.py" +ynh_add_config --template="setup_user.py" --destination="$data_dir/setup_user.py" +ynh_add_config --template="urls.py" --destination="$data_dir/urls.py" +ynh_add_config --template="wsgi.py" --destination="$data_dir/wsgi.py" -touch "$final_path/local_settings.py" +touch "$data_dir/local_settings.py" #================================================= # MIGRATE / COLLECTSTATIC / CREATEADMIN #================================================= ynh_script_progression --message="migrate/collectstatic/createadmin..." --weight=10 -cd "$final_path" || exit +cd "$data_dir" || exit # Just for debugging: ./manage.py diffsettings @@ -174,72 +108,46 @@ cd "$final_path" || exit # This may fail in some cases with errors, etc., but the app works and the user can fix issues later. ./manage.py check --deploy || true - -#================================================= -# SETUP LOGROTATE -#================================================= -ynh_script_progression --message="Configuring log rotation..." - -# Use logrotate to manage app-specific logfile(s) -ynh_use_logrotate "$log_file" - #================================================= # INTEGRATE SERVICE IN YUNOHOST #================================================= ynh_script_progression --message="Integrating service in YunoHost..." -yunohost service add $app --log="${log_file}" +yunohost service add $app #================================================= # GENERIC FINALIZATION #================================================= # SECURE FILES AND DIRECTORIES #================================================= - -# Set permissions to app files -chown -R "$app:" "$log_path" -chown -R "$app:www-data" "$public_path" -chown -R "$app:" "$final_path" - -chmod o-rwx "$log_path" -chmod o-rwx "$public_path" -chmod o-rwx "$final_path" +ynh_script_progression --message="Set file permissions..." +myynh_fix_file_permissions #================================================= # SETUP SYSTEMD #================================================= ynh_script_progression --message="Configuring systemd service '$app'..." --weight=5 -# https://yunohost.org/en/contribute/packaging_apps/helpers +# https://yunohost.org/en/packaging_apps_helpers#ynh-add-systemd-config # https://github.com/YunoHost/yunohost/blob/dev/helpers/systemd -ynh_add_systemd_config --service="$app" --template="systemd.service" - -#================================================= -# SETUP SSOWAT -#================================================= -ynh_script_progression --message="Configuring SSOwat..." - -# Make app public if necessary or protect it -if [ $is_public -eq 1 ] -then - # Everyone can access the app. - # The "main" permission is automatically created before the install script. - ynh_permission_update --permission "main" --add "visitors" -fi +ynh_add_systemd_config --service=$app --template="systemd.service" #================================================= # Start the app server via systemd #================================================= ynh_script_progression --message="Starting systemd service '$app'..." --weight=5 -ynh_systemd_action --service_name="$app" --action="start" +ynh_systemd_action --service_name=$app --action="start" --log_path="$log_file" #================================================= -# RELOAD NGINX +# NGINX CONFIGURATION #================================================= -ynh_script_progression --message="Reloading nginx web server..." +ynh_script_progression --message="Configuring nginx web server..." -ynh_systemd_action --service_name="nginx" --action="reload" +# Create a dedicated nginx config +# https://yunohost.org/en/contribute/packaging_apps/helpers +# https://github.com/YunoHost/yunohost/blob/dev/helpers/nginx +ynh_add_nginx_config "public_path" "port" #================================================= # END OF SCRIPT diff --git a/scripts/remove b/scripts/remove index dc573b8..56f7a77 100755 --- a/scripts/remove +++ b/scripts/remove @@ -9,17 +9,6 @@ source _common.sh source /usr/share/yunohost/helpers -#================================================= -# LOAD SETTINGS -#================================================= -ynh_script_progression --message="Loading installation settings..." - -domain=$(ynh_app_setting_get --app="$app" --key=domain) -db_name=$(ynh_app_setting_get --app="$app" --key=db_name) -db_user=$db_name -public_path=$(ynh_app_setting_get --app="$app" --key=public_path) -final_path=$(ynh_app_setting_get --app="$app" --key=final_path) - #================================================= # STANDARD REMOVE #================================================= @@ -27,10 +16,10 @@ final_path=$(ynh_app_setting_get --app="$app" --key=final_path) #================================================= # Remove a service from the admin panel, added by `yunohost service add` -if yunohost service status "$app" >/dev/null 2>&1 +if yunohost service status $app >/dev/null 2>&1 then ynh_script_progression --message="Removing $app service integration..." - yunohost service remove "$app" + yunohost service remove $app fi #================================================= @@ -38,15 +27,7 @@ fi #================================================= ynh_script_progression --message="Stopping and removing systemd service '$app'..." --weight=5 -ynh_remove_systemd_config --service="$app" - -#================================================= -# REMOVE THE PostgreSQL DATABASE -#================================================= -ynh_script_progression --message="Removing the PostgreSQL database..." - -# Remove a database if it exists, along with the associated user -ynh_psql_remove_db --db_user=$db_user --db_name=$db_name +ynh_remove_systemd_config --service=$app ##================================================= ## REMOVE REDIS DB @@ -54,22 +35,16 @@ ynh_psql_remove_db --db_user=$db_user --db_name=$db_name ynh_redis_remove_db -#================================================= -# REMOVE DEPENDENCIES -#================================================= -ynh_script_progression --message="Removing dependencies..." --weight=10 - -# Remove metapackage and its dependencies -ynh_exec_warn_less ynh_remove_app_dependencies - #================================================= # REMOVE APP MAIN DIR #================================================= ynh_script_progression --message="Removing app main directory..." -# Remove the app directory securely -ynh_secure_remove --file="$public_path" -ynh_secure_remove --file="$final_path" +# /var/www/$app/ +ynh_secure_remove --file="$install_dir" + +# /home/yunohost.app/$app/ +ynh_secure_remove --file="$data_dir" #================================================= # REMOVE NGINX CONFIGURATION @@ -87,16 +62,6 @@ ynh_script_progression --message="Removing logrotate configuration..." # Remove the app-specific logrotate config ynh_remove_logrotate -#================================================= -# GENERIC FINALIZATION -#================================================= -# REMOVE DEDICATED USER -#================================================= -ynh_script_progression --message="Removing the dedicated system user..." - -# Delete a system user -ynh_system_user_delete --username="$app" - #================================================= # END OF SCRIPT #================================================= diff --git a/scripts/restore b/scripts/restore index a72837e..77cb45c 100755 --- a/scripts/restore +++ b/scripts/restore @@ -9,39 +9,12 @@ source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -#================================================= -# MANAGE SCRIPT FAILURE -#================================================= - -ynh_abort_if_errors - -#================================================= -# LOAD SETTINGS -#================================================= -ynh_script_progression --message="Loading settings..." - -final_path=$(ynh_app_setting_get --app="$app" --key=final_path) -public_path=$(ynh_app_setting_get --app="$app" --key=public_path) -db_name=$(ynh_app_setting_get --app="$app" --key=db_name) -db_user=$db_name -db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd) - -domain=$(ynh_app_setting_get --app="$app" --key=domain) -path_url=$(ynh_app_setting_get --app="$app" --key=path) - -#================================================= -# CHECK IF THE APP CAN BE RESTORED -#================================================= -ynh_script_progression --message="Validating restoration parameters..." - -test ! -d $final_path \ - || ynh_die --message="There is already a directory: $final_path " - #================================================= # STANDARD RESTORATION STEPS #================================================= # RESTORE THE NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Restoring the NGINX web server configuration..." --weight=1 ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" @@ -50,74 +23,31 @@ ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" #================================================= ynh_script_progression --message="Restoring $app main directory..." -ynh_restore_file --origin_path="$final_path" -ynh_restore_file --origin_path="$public_path" +ynh_restore_file --origin_path="$install_dir" +ynh_restore_file --origin_path="$data_dir" -#================================================= -# RECREATE THE DEDICATED USER -#================================================= -ynh_script_progression --message="Recreating the dedicated system user..." - -# Create the dedicated user (if not existing) -ynh_system_user_create --username=$app --home_dir="$final_path" --use_shell - -#================================================= -# RESTORE USER RIGHTS -#================================================= - -# Restore permissions on app files -chown -R "$app:www-data" "$public_path" -chown -R "$app:" "$final_path" - -#================================================= -# SPECIFIC RESTORATION -#================================================= -# REINSTALL DEPENDENCIES -#================================================= -ynh_script_progression --message="Reinstalling dependencies..." --weight=20 - -ynh_exec_warn_less ynh_install_app_dependencies "$pkg_dependencies" +ynh_script_progression --message="Set file permissions..." +myynh_fix_file_permissions #================================================= # PYTHON VIRTUALENV # Maybe the backup contains a other Python version #================================================= -ynh_script_progression --message="Recreate Python virtualenv..." --weight=5 +ynh_script_progression --message="Create and setup Python virtualenv..." --weight=45 -# Always recreate everything fresh with current python version -ynh_secure_remove "${final_path}/venv" - -# Skip pip because of: https://github.com/YunoHost/issues/issues/1960 -python3 -m venv --without-pip "${final_path}/venv" -chown -R "$app:" "$final_path" - -#================================================= -# PIP INSTALLATION -#================================================= -ynh_script_progression --message="Install project via pip..." --weight=45 -#run source in a 'sub shell' -( - set +o nounset - source "${final_path}/venv/bin/activate" - set -o nounset - ynh_exec_as $app $final_path/venv/bin/python3 -m ensurepip - ynh_exec_as $app $final_path/venv/bin/pip3 install --upgrade wheel pip setuptools - ynh_exec_as $app $final_path/venv/bin/pip3 install --no-deps -r "$final_path/requirements.txt" -) +myynh_setup_python_venv #================================================= # RESTORE THE PostgreSQL DATABASE #================================================= ynh_script_progression --message="Restoring the PostgreSQL database..." --weight=5 -ynh_psql_test_if_first_run -ynh_psql_setup_db --db_user="$db_user" --db_name="$db_name" --db_pwd="$db_pwd" ynh_psql_connect_as --user=$db_user --password=$db_pwd --database=$db_name < ./db.sql #================================================= # RESTORE SYSTEMD #================================================= -ynh_script_progression --message="Restoring the systemd configuration..." +ynh_script_progression --message="Restoring the systemd $app configuration..." ynh_restore_file --origin_path="/etc/systemd/system/$app.service" systemctl enable $app.service --quiet @@ -127,15 +57,14 @@ systemctl enable $app.service --quiet #================================================= ynh_script_progression --message="Integrating service in YunoHost..." -yunohost service add $app --log="${log_file}" +yunohost service add $app #================================================= # RESTORE THE LOGROTATE CONFIGURATION #================================================= +ynh_script_progression --message="Setup logging..." -mkdir -p "$log_path" -touch "${log_file}" -chown -R "$app:" "$log_path" +myynh_setup_log_file ynh_restore_file --origin_path="/etc/logrotate.d/$app" #================================================= @@ -143,15 +72,8 @@ ynh_restore_file --origin_path="/etc/logrotate.d/$app" #================================================= # SECURE FILES AND DIRECTORIES #================================================= - -# Set permissions to app files -chown -R "$app:" "$log_path" -chown -R "$app:www-data" "$public_path" -chown -R "$app:" "$final_path" - -chmod o-rwx "$log_path" -chmod o-rwx "$public_path" -chmod o-rwx "$final_path" +ynh_script_progression --message="Set file permissions..." +myynh_fix_file_permissions #================================================= # GENERIC FINALIZATION @@ -160,7 +82,7 @@ chmod o-rwx "$final_path" #================================================= ynh_script_progression --message="Starting systemd service '$app'..." --weight=5 -ynh_systemd_action --service_name="$app" --action="start" +ynh_systemd_action --service_name=$app --action="start" --log_path="$log_file" #================================================= # RELOAD NGINX diff --git a/scripts/upgrade b/scripts/upgrade index 9bdc8f1..36de96b 100755 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -7,68 +7,29 @@ source _common.sh source /usr/share/yunohost/helpers -#================================================= -# LOAD SETTINGS -#================================================= -ynh_script_progression --message="Loading installation settings..." - -admin=$(ynh_app_setting_get --app="$app" --key=admin) -public_path=$(ynh_app_setting_get --app="$app" --key=public_path) -final_path=$(ynh_app_setting_get --app="$app" --key=final_path) -log_path=$(ynh_app_setting_get --app="$app" --key=log_path) - -domain=$(ynh_app_setting_get --app="$app" --key=domain) -path_url=$(ynh_app_setting_get --app="$app" --key=path) - -port=$(ynh_app_setting_get --app="$app" --key=port) - -db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd) -db_name=$(ynh_sanitize_dbid --db_name="$app") -db_user=$db_name - -redis_db=$(ynh_app_setting_get --app="$app" --key=redis_db) - #------------------------------------------------- # config_panel.toml settings: -debug_enabled=$(ynh_app_setting_get --app="$app" --key=debug_enabled) if [ -z "$debug_enabled" ]; then debug_enabled="0" - ynh_app_setting_set --app="$app" --key=debug_enabled --value="$debug_enabled" + ynh_app_setting_set --app=$app --key=debug_enabled --value="$debug_enabled" fi -log_level=$(ynh_app_setting_get --app="$app" --key=log_level) if [ -z "$log_level" ]; then log_level="WARNING" - ynh_app_setting_set --app="$app" --key=log_level --value="$log_level" + ynh_app_setting_set --app=$app --key=log_level --value="$log_level" fi -admin_email=$(ynh_app_setting_get --app="$app" --key=admin_email) if [ -z "$admin_email" ]; then admin_email="${admin}@${domain}" - ynh_app_setting_set --app="$app" --key=admin_email --value="$admin_email" + ynh_app_setting_set --app=$app --key=admin_email --value="$admin_email" fi -default_from_email=$(ynh_app_setting_get --app="$app" --key=default_from_email) if [ -z "$default_from_email" ]; then default_from_email="${app}@${domain}" - ynh_app_setting_set --app="$app" --key=default_from_email --value="$default_from_email" + ynh_app_setting_set --app=$app --key=default_from_email --value="$default_from_email" fi -#================================================= -# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP -#================================================= -ynh_script_progression --message="Backing up $app before upgrading (may take a while)..." --weight=40 - -# Backup the current version of the app -ynh_backup_before_upgrade -ynh_clean_setup () { - # restore it if the upgrade fails - ynh_restore_upgradebackup -} -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors - #================================================= # STANDARD UPGRADE STEPS #================================================= @@ -76,91 +37,44 @@ ynh_abort_if_errors #================================================= ynh_script_progression --message="Stopping systemd service '$app'..." --weight=5 -ynh_systemd_action --service_name="$app" --action="stop" +ynh_systemd_action --service_name=$app --action="stop" --log_path="$log_file" -#================================================= -# NGINX CONFIGURATION -#================================================= -ynh_script_progression --message="Upgrading nginx web server configuration..." - -# Create a dedicated nginx config -# https://yunohost.org/en/contribute/packaging_apps/helpers -# https://github.com/YunoHost/yunohost/blob/dev/helpers/nginx -ynh_add_nginx_config "public_path" "port" - -#================================================= -# SPECIFIC UPGRADE -#================================================= -# Update dependencies -#================================================= -ynh_script_progression --message="Upgrading dependencies..." --weight=20 - -ynh_exec_warn_less ynh_install_app_dependencies "$pkg_dependencies" - -#================================================= -# CREATE DEDICATED USER -#================================================= -ynh_script_progression --message="Making sure dedicated system user exists..." - -# Create a system user -ynh_system_user_create --username="$app" --home_dir="$final_path" --use_shell #================================================= # SETUP SYSTEMD #================================================= ynh_script_progression --message="Configuring systemd service '$app'..." --weight=5 -ynh_add_systemd_config --service="$app" --template="systemd.service" +ynh_add_systemd_config --service=$app --template="systemd.service" #================================================= # PYTHON VIRTUALENV #================================================= -ynh_script_progression --message="Recreate Python virtualenv..." --weight=5 - -# Always recreate everything fresh with current python version -ynh_secure_remove "${final_path}/venv" - -# Skip pip because of: https://github.com/YunoHost/issues/issues/1960 -python3 -m venv --without-pip "${final_path}/venv" - -cp ../conf/requirements.txt "$final_path/requirements.txt" -chown -R "$app:" "$final_path" - -#================================================= -# PIP INSTALLATION -#================================================= -ynh_script_progression --message="Install project via pip..." --weight=45 -#run source in a 'sub shell' -( - set +o nounset - source "${final_path}/venv/bin/activate" - set -o nounset - ynh_exec_as $app $final_path/venv/bin/python3 -m ensurepip - ynh_exec_as $app $final_path/venv/bin/pip3 install --upgrade wheel pip setuptools - ynh_exec_as $app $final_path/venv/bin/pip3 install --no-deps -r "$final_path/requirements.txt" -) +ynh_script_progression --message="Create and setup Python virtualenv..." --weight=45 +cp ../conf/requirements.txt "$data_dir/requirements.txt" +myynh_setup_python_venv #================================================= # copy config files # ================================================ ynh_script_progression --message="Create project configuration files..." -ynh_add_config --template="gunicorn.conf.py" --destination="$final_path/gunicorn.conf.py" +ynh_add_config --template="gunicorn.conf.py" --destination="$data_dir/gunicorn.conf.py" -ynh_add_config --template="manage.py" --destination="$final_path/manage.py" -chmod +x "$final_path/manage.py" +ynh_add_config --template="manage.py" --destination="$data_dir/manage.py" +chmod -c +x "$data_dir/manage.py" -ynh_add_config --template="settings.py" --destination="$final_path/settings.py" -ynh_add_config --template="setup_user.py" --destination="$final_path/setup_user.py" -ynh_add_config --template="urls.py" --destination="$final_path/urls.py" -ynh_add_config --template="wsgi.py" --destination="$final_path/wsgi.py" +ynh_add_config --template="settings.py" --destination="$data_dir/settings.py" +ynh_add_config --template="setup_user.py" --destination="$data_dir/setup_user.py" +ynh_add_config --template="urls.py" --destination="$data_dir/urls.py" +ynh_add_config --template="wsgi.py" --destination="$data_dir/wsgi.py" #================================================= # MIGRATE PYINVENTORY #================================================= ynh_script_progression --message="migrate/collectstatic/createadmin..." --weight=10 -cd "$final_path" || exit +cd "$data_dir" || exit # Just for debugging: ./manage.py diffsettings @@ -182,43 +96,23 @@ cd "$final_path" || exit ynh_script_progression --message="Upgrading logrotate configuration..." # Use logrotate to manage app-specific logfile(s) -ynh_use_logrotate --non-append - -#================================================= -# INTEGRATE SERVICE IN YUNOHOST -#================================================= -ynh_script_progression --message="Integrating service in YunoHost..." - -yunohost service add $app --log="${log_file}" +ynh_use_logrotate --logfile="$log_file" --specific_user=$app --non-append #================================================= # GENERIC FINALIZATION #================================================= # SECURE FILES AND DIRECTORIES #================================================= - -# Set permissions to app files -chown -R "$app:" "$log_path" -chown -R "$app:www-data" "$public_path" -chown -R "$app:" "$final_path" - -chmod o-rwx "$log_path" -chmod o-rwx "$public_path" -chmod o-rwx "$final_path" +ynh_script_progression --message="Set file permissions..." +myynh_fix_file_permissions #================================================= # Start the app server via systemd #================================================= ynh_script_progression --message="Starting systemd service '$app'..." --weight=5 -ynh_systemd_action --service_name="$app" --action="start" - -#================================================= -# RELOAD NGINX -#================================================= -ynh_script_progression --message="Reloading nginx web server..." - -ynh_systemd_action --service_name=nginx --action=reload +yunohost service add $app +ynh_systemd_action --service_name=$app --action="start" --log_path="$log_file" #================================================= # END OF SCRIPT diff --git a/tests.toml b/tests.toml new file mode 100644 index 0000000..4221e9f --- /dev/null +++ b/tests.toml @@ -0,0 +1,31 @@ +test_format = 1.0 + +[default] + + # ------------ + # Tests to run + # ------------ + + # NB: the tests to run are automatically deduced by the CI script according to the + # content of the app's manifest. The declarations below allow to customize which + # tests are ran, possibly add special test suite to test special args, or + # declare which commits to test upgrade from. + # + # You can also decide (though this is discouraged!) to ban/ignore some tests, + + # The test IDs to be used in only/exclude statements are: + # install.root, install.subdir, install.nourl, install.multi, backup_restore, upgrade, upgrade.someCommitId change_url + #exclude = ["install.private", "install.multi"] + + # ------------------------------- + # Default args to use for install + # ------------------------------- + + # By default, the CI will automagically fill the 'standard' args + # such as domain, path, admin, is_public and password with relevant values + # and also install args with a "default" provided in the manifest.. + # It should only make sense to declare custom args here for args with no default values + + args.default_from_email = "default_from_email@example.tld" + args.admin_email = "admin_email@example.tld" + diff --git a/tests/conftest.py b/tests/conftest.py index 75f20f0..8e36ec5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,7 +11,7 @@ import sys from pathlib import Path import django -from django_yunohost_integration.local_test import create_local_test +from django_yunohost_integration.local_test import CreateResults, create_local_test BASE_PATH = Path(__file__).parent.parent @@ -21,23 +21,23 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' def pytest_configure(): print('Compile YunoHost files...') - final_path = create_local_test( + result: CreateResults = create_local_test( django_settings_path=BASE_PATH / 'conf' / 'settings.py', destination=BASE_PATH / 'local_test', runserver=False, extra_replacements={ - '__DEBUG_ENABLED__': '0', + '__DEBUG_ENABLED__': 'NO', # "YES" or "NO" string '__LOG_LEVEL__': 'INFO', '__ADMIN_EMAIL__': 'foo-bar@test.tld', '__DEFAULT_FROM_EMAIL__': 'django_app@test.tld', }, ) - print('Local test files created here:') - print(f'"{final_path}"') + print('Local test files created:') + print(result) - os.chdir(final_path) - final_home_str = str(final_path) - if final_home_str not in sys.path: - sys.path.insert(0, final_home_str) + os.chdir(result.data_dir_path) + data_dir = str(result.data_dir_path) + if data_dir not in sys.path: + sys.path.insert(0, data_dir) django.setup() diff --git a/tests/test_django_project.py b/tests/test_django_project.py index ff7bd41..0febee1 100644 --- a/tests/test_django_project.py +++ b/tests/test_django_project.py @@ -27,16 +27,16 @@ class DjangoYnhTestCase(HtmlAssertionMixin, TestCase): assert settings.PATH_URL == 'app_path' - assert str(settings.FINALPATH).endswith('/local_test/opt_yunohost') - assert str(settings.PUBLIC_PATH).endswith('/local_test/var_www') - assert str(settings.LOG_FILE).endswith('/local_test/var_log_pyinventory.log') + assert str(settings.DATA_DIR_PATH).endswith('/local_test/opt_yunohost') + assert str(settings.INSTALL_DIR_PATH).endswith('/local_test/var_www') + assert str(settings.LOG_FILE_PATH).endswith('/local_test/var_log_pyinventory.log') assert settings.ROOT_URLCONF == 'urls' assert reverse('admin:index') == '/app_path/' def test_config_panel_settings(self): # config_panel.toml settings, set via tests.conftest.pytest_configure(): - assert settings.DEBUG_ENABLED == '0' and settings.DEBUG is False + assert settings.DEBUG_ENABLED == 'NO' and settings.DEBUG is False assert settings.LOG_LEVEL == 'INFO' assert settings.ADMIN_EMAIL == 'foo-bar@test.tld' assert settings.DEFAULT_FROM_EMAIL == 'django_app@test.tld' diff --git a/tests/test_django_project_create_unknown_user_1.snapshot.html b/tests/test_django_project_create_unknown_user_1.snapshot.html index 37c99de..82b7b75 100644 --- a/tests/test_django_project_create_unknown_user_1.snapshot.html +++ b/tests/test_django_project_create_unknown_user_1.snapshot.html @@ -28,11 +28,34 @@ Log out +
-
+

diff --git a/tests/test_project_setup.py b/tests/test_project_setup.py index ef75577..1b50809 100644 --- a/tests/test_project_setup.py +++ b/tests/test_project_setup.py @@ -50,8 +50,8 @@ def test_version(): manifest_version = pyproject_version.replace('+', '~') assert_file_contains_string( - file_path=Path(PACKAGE_ROOT, 'manifest.json'), - string=f'"version": "{manifest_version}"', + file_path=Path(PACKAGE_ROOT, 'manifest.toml'), + string=f'version = "{manifest_version}"', ) @@ -143,15 +143,36 @@ def test_check_code_style(): raise AssertionError(f'Linting error:\n{"-"*100}\n{err.stdout}\n{"-"*100}') -class ConfigPanelTestCase(TestCase): - def test_config_panel_toml(self): - config_panel_path = PACKAGE_ROOT / 'config_panel.toml' - assert_is_file(config_panel_path) +class ManifestTestCase(TestCase): + def test_manifest_toml(self): + manifest_path = PACKAGE_ROOT / 'manifest.toml' + assert_is_file(manifest_path) - cfg = tomllib.loads(config_panel_path.read_text(encoding='UTF-8')) + cfg = tomllib.loads(manifest_path.read_text(encoding='UTF-8')) - self.assertEqual(cfg['version'], '1.0') + self.assertEqual(cfg['packaging_format'], 2) self.assertEqual( - set(cfg['main']['config'].keys()), - {'name', 'default_from_email', 'admin_email', 'debug_enabled', 'log_level'}, + set(cfg['install'].keys()), + { + 'admin', + 'admin_email', + 'debug_enabled', + 'default_from_email', + 'domain', + 'init_main_permission', + 'log_level', + 'path', + }, + ) + self.assertEqual( + set(cfg['resources'].keys()), + { + 'apt', + 'data_dir', + 'database', + 'install_dir', + 'permissions', + 'ports', + 'system_user', + }, )