[core] Don't read configs at the module top-level

This commit is contained in:
Thomas Lindner 2023-03-18 18:16:57 +01:00
parent 003a10b273
commit 35eff0c416
5 changed files with 64 additions and 73 deletions

View file

@ -14,12 +14,13 @@
0. `cd backend` 0. `cd backend`
1. Activate your dev environment with `source .venv/bin/activate` 1. Activate your dev environment with `source .venv/bin/activate`
2. Install with `pip install .` 2. Install with `pip install .`
3. Turn off production mode: `sudo su -c 'echo "production = 0" >> /etc/kibicara.conf'` 3. Create a config file: `echo "production = 0" > kibicara.conf`
#### Cheatsheet #### Cheatsheet
- Install Kibicara with `pip install .` - Install Kibicara with `pip install .`
- Execute Kibicara with `kibicara` (verbose: `kibicara -vvv`) - Execute Kibicara with `kibicara -f kibicara.conf`
(verbose: `kibicara -vvv -f kibicara.conf`)
- Interact with Swagger REST-API Documentation: `http://localhost:8000/api/docs` - Interact with Swagger REST-API Documentation: `http://localhost:8000/api/docs`
- Test and stylecheck with `tox` - Test and stylecheck with `tox`
- Fix style issues with `black -S src tests` - Fix style issues with `black -S src tests`

View file

@ -1,4 +1,4 @@
Copyright (C) 2020 by Thomas Lindner <tom@dl6tom.de> Copyright (C) 2020, 2023 by Thomas Lindner <tom@dl6tom.de>
Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de> Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de>
Copyright (C) 2020 by Christian Hagenest <c.hagenest@pm.me> Copyright (C) 2020 by Christian Hagenest <c.hagenest@pm.me>
Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org> Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org>

View file

@ -1,29 +1,16 @@
# Copyright (C) 2020 by Thomas Lindner <tom@dl6tom.de> # Copyright (C) 2020, 2023 by Thomas Lindner <tom@dl6tom.de>
# Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de> # Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de>
# Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org> # Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org>
# #
# SPDX-License-Identifier: 0BSD # SPDX-License-Identifier: 0BSD
"""Configuration file and command line argument parser.
Gives a dictionary named `config` with configuration parsed either from
`/etc/kibicara.conf` or from a file given by command line argument `-f`.
If no configuration was found at all, the defaults are used.
Example:
```
from kibicara.config import config
print(config)
```
"""
from argparse import ArgumentParser
from sys import argv
from nacl.secret import SecretBox from nacl.secret import SecretBox
from nacl.utils import random from nacl.utils import random
from pytoml import load
"""Default configuration.
The default configuration gets overwritten by a configuration file if one exists.
"""
config = { config = {
'database_connection': 'sqlite:////tmp/kibicara.sqlite', 'database_connection': 'sqlite:////tmp/kibicara.sqlite',
'frontend_url': 'http://localhost:4200', # url of frontend, change in prod 'frontend_url': 'http://localhost:4200', # url of frontend, change in prod
@ -38,47 +25,3 @@ config = {
'root_url': 'http://localhost:8000', # url of backend 'root_url': 'http://localhost:8000', # url of backend
'cors_allow_origin': 'http://localhost:4200', 'cors_allow_origin': 'http://localhost:4200',
} }
"""Default configuration.
The default configuration gets overwritten by a configuration file if one exists.
"""
args = None
if argv[0].endswith('kibicara'):
parser = ArgumentParser()
parser.add_argument(
'-f',
'--config',
dest='configfile',
default='/etc/kibicara.conf',
help='path to config file',
)
parser.add_argument(
'-v',
'--verbose',
action='count',
help='Raise verbosity level',
)
args = parser.parse_args()
if argv[0].endswith('kibicara_mda'):
parser = ArgumentParser()
parser.add_argument(
'-f',
'--config',
dest='configfile',
default='/etc/kibicara.conf',
help='path to config file',
)
# the MDA passes the recipient address as command line argument
parser.add_argument('recipient')
args = parser.parse_args()
if args is not None:
try:
with open(args.configfile) as configfile:
config.update(load(configfile))
except FileNotFoundError:
# run with default config
pass

View file

@ -1,4 +1,4 @@
# Copyright (C) 2020 by Thomas Lindner <tom@dl6tom.de> # Copyright (C) 2020, 2023 by Thomas Lindner <tom@dl6tom.de>
# Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de> # Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de>
# Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org> # Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org>
# #
@ -6,6 +6,7 @@
"""Entrypoint of Kibicara.""" """Entrypoint of Kibicara."""
from argparse import ArgumentParser
from asyncio import run as asyncio_run from asyncio import run as asyncio_run
from logging import DEBUG, INFO, WARNING, basicConfig, getLogger from logging import DEBUG, INFO, WARNING, basicConfig, getLogger
@ -14,8 +15,9 @@ from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from hypercorn.asyncio import serve from hypercorn.asyncio import serve
from hypercorn.config import Config from hypercorn.config import Config
from pytoml import load
from kibicara.config import args, config from kibicara.config import config
from kibicara.model import Mapping from kibicara.model import Mapping
from kibicara.platformapi import Spawner from kibicara.platformapi import Spawner
from kibicara.webapi import router from kibicara.webapi import router
@ -31,9 +33,29 @@ class Main:
""" """
def __init__(self): def __init__(self):
asyncio_run(self.__run()) parser = ArgumentParser()
parser.add_argument(
'-f',
'--config',
dest='configfile',
default='/etc/kibicara.conf',
help='path to config file',
)
parser.add_argument(
'-v',
'--verbose',
action='count',
help='Raise verbosity level',
)
args = parser.parse_args()
try:
with open(args.configfile) as configfile:
config.update(load(configfile))
except FileNotFoundError:
# run with default config
pass
async def __run(self):
LOGLEVELS = { LOGLEVELS = {
None: WARNING, None: WARNING,
1: INFO, 1: INFO,
@ -45,6 +67,9 @@ class Main:
) )
getLogger('aiosqlite').setLevel(WARNING) getLogger('aiosqlite').setLevel(WARNING)
Mapping.create_all() Mapping.create_all()
asyncio_run(self.__run())
async def __run(self):
await Spawner.init_all() await Spawner.init_all()
await self.__start_webserver() await self.__start_webserver()

View file

@ -1,10 +1,11 @@
# Copyright (C) 2020 by Maike <maike@systemli.org> # Copyright (C) 2020 by Maike <maike@systemli.org>
# Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de> # Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de>
# Copyright (C) 2020 by Thomas Lindner <tom@dl6tom.de> # Copyright (C) 2020, 2023 by Thomas Lindner <tom@dl6tom.de>
# Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org> # Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org>
# #
# SPDX-License-Identifier: 0BSD # SPDX-License-Identifier: 0BSD
from argparse import ArgumentParser
from asyncio import run as asyncio_run from asyncio import run as asyncio_run
from email.parser import BytesParser from email.parser import BytesParser
from email.policy import default from email.policy import default
@ -15,9 +16,10 @@ from sys import stdin
from fastapi import status from fastapi import status
from ormantic import NoMatch from ormantic import NoMatch
from pytoml import load
from requests import post from requests import post
from kibicara.config import args, config from kibicara.config import config
from kibicara.platforms.email.model import Email, EmailSubscribers from kibicara.platforms.email.model import Email, EmailSubscribers
logger = getLogger(__name__) logger = getLogger(__name__)
@ -25,11 +27,31 @@ logger = getLogger(__name__)
class Main: class Main:
def __init__(self): def __init__(self):
asyncio_run(self.__run()) parser = ArgumentParser()
parser.add_argument(
'-f',
'--config',
dest='configfile',
default='/etc/kibicara.conf',
help='path to config file',
)
# the MDA passes the recipient address as command line argument
parser.add_argument('recipient')
args = parser.parse_args()
try:
with open(args.configfile) as configfile:
config.update(load(configfile))
except FileNotFoundError:
# run with default config
pass
async def __run(self):
# extract email from the recipient # extract email from the recipient
email_name = args.recipient.lower() email_name = args.recipient.lower()
asyncio_run(self.__run(email_name))
async def __run(self, email_name):
try: try:
email = await Email.objects.get(name=email_name) email = await Email.objects.get(name=email_name)
except NoMatch: except NoMatch: