🔀 Merge branch 'fix-38' into 'develop'

 — Create command to generate example configuration (fix #38)

See merge request framasoft/framaspace/argos!54
This commit is contained in:
Luc Didry 2024-05-28 14:44:46 +00:00
commit 609b6ad580
8 changed files with 98 additions and 77 deletions

View file

@ -5,6 +5,7 @@
- 💄📯 — Improve notifications and result(s) pages - 💄📯 — Improve notifications and result(s) pages
- 🔊 — Add level of log before the log message - 🔊 — Add level of log before the log message
— 🔊 — Add a warning messages in the logs if there is no tasks in database. (fix #41) — 🔊 — Add a warning messages in the logs if there is no tasks in database. (fix #41)
- ✨ — Add command to generate example configuration (fix #38)
## 0.1.1 ## 0.1.1

View file

@ -1,6 +1,7 @@
import asyncio import asyncio
import os import os
from functools import wraps from functools import wraps
from pathlib import Path
from uuid import uuid4 from uuid import uuid4
import click import click
@ -32,10 +33,11 @@ def coroutine(f):
def validate_config_access(ctx, param, value): def validate_config_access(ctx, param, value):
if os.path.isfile(value) and os.access(value, os.R_OK): path = Path(value)
if path.is_file() and os.access(path, os.R_OK):
return value return value
if os.path.isfile(value): if path.is_file():
raise click.BadParameter(f"the file {value} is not readabale.") raise click.BadParameter(f"the file {value} is not readabale.")
raise click.BadParameter(f"the file {value} does not exists or is not reachable.") raise click.BadParameter(f"the file {value} does not exists or is not reachable.")
@ -226,8 +228,8 @@ async def migrate(config):
settings = get_app_settings() settings = get_app_settings()
current_dir = os.path.dirname(__file__) current_dir = Path(__file__).resolve().parent
alembic_cfg = Config(os.path.join(current_dir, "server/migrations/alembic.ini")) alembic_cfg = Config(current_dir / "server" / "migrations" / "alembic.ini")
alembic_cfg.set_main_option("sqlalchemy.url", settings.database_url) alembic_cfg.set_main_option("sqlalchemy.url", settings.database_url)
command.upgrade(alembic_cfg, "head") command.upgrade(alembic_cfg, "head")
@ -242,5 +244,19 @@ async def generate_token():
click.echo(uuid4()) click.echo(uuid4())
@server.command()
@coroutine
async def generate_config():
"""Output an example config file.
\b
Redirect the output to a file to save it:
argos server generate-config > /etc/argos/config.yaml
"""
config_example = Path(__file__).resolve().parent / "config-example.yaml"
with config_example.open("r", encoding="utf-8") as f:
print(f.read())
if __name__ == "__main__": if __name__ == "__main__":
cli() cli()

66
argos/config-example.yaml Normal file
View file

@ -0,0 +1,66 @@
general:
frequency: "1m" # Run checks every minute.
# Which way do you want to be warned when a check goes to that severity?
# "local" emits a message in the server log
alerts:
ok:
- local
warning:
- local
critical:
- local
unknown:
- local
# mail:
# mailfrom: no-reply@example.org
# host: 127.0.0.1
# port: 25
# ssl: False
# starttls: False
# auth:
# login: foo
# password: bar
# addresses:
# - foo@admin.example.org
# - bar@admin.example.org
# gotify:
# - url: https://example.org
# tokens:
# - foo
# - bar
service:
secrets:
# Secrets can be generated using `argos server generate-token`.
# You need at least one. Write them as a list, like:
# - secret_token
ssl:
thresholds:
- "1d": critical
- "5d": warning
# It's also possible to define the checks in another file
# with the include syntax:
#
# websites: !include websites.yaml
#
websites:
- domain: "https://mypads.example.org"
paths:
- path: "/mypads/"
checks:
- status-is: 200
- body-contains: '<div id= "mypads"></div>'
- ssl-certificate-expiration: "on-check"
- path: "/admin/"
checks:
- status-is: 401
- domain: "https://munin.example.org"
paths:
- path: "/"
checks:
- status-is: 301
- path: "/munin/"
checks:
- status-is: 401

View file

@ -1,5 +1,5 @@
import os
import sys import sys
from pathlib import Path
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
@ -35,7 +35,7 @@ def get_application() -> FastAPI:
appli.include_router(routes.api, prefix="/api") appli.include_router(routes.api, prefix="/api")
appli.include_router(routes.views) appli.include_router(routes.views)
static_dir = os.path.join(os.path.dirname(__file__), "static") static_dir = Path(__file__).resolve().parent / "static"
appli.mount("/static", StaticFiles(directory=static_dir), name="static") appli.mount("/static", StaticFiles(directory=static_dir), name="static")
return appli return appli

View file

@ -1,7 +1,7 @@
"""Web interface for humans""" """Web interface for humans"""
from collections import defaultdict from collections import defaultdict
from functools import cmp_to_key from functools import cmp_to_key
from os import path from pathlib import Path
from typing import Annotated from typing import Annotated
from urllib.parse import urlparse from urllib.parse import urlparse
@ -18,8 +18,8 @@ from argos.server.routes.dependencies import get_config, get_db
route = APIRouter() route = APIRouter()
current_dir = path.dirname(__file__) current_dir = Path(__file__).resolve().parent
templates = Jinja2Templates(directory=path.join(current_dir, "../templates")) templates = Jinja2Templates(directory=current_dir / ".." / "templates")
SEVERITY_LEVELS = {"ok": 1, "warning": 2, "critical": 3, "unknown": 4} SEVERITY_LEVELS = {"ok": 1, "warning": 2, "critical": 3, "unknown": 4}

View file

@ -1,7 +1,7 @@
"""Pydantic schemas for server""" """Pydantic schemas for server"""
import os
from functools import lru_cache from functools import lru_cache
from os import environ from os import environ
from pathlib import Path
from typing import Optional, Union from typing import Optional, Union
import yaml import yaml
@ -77,9 +77,9 @@ def read_yaml_config(filename):
def _load_yaml(filename): def _load_yaml(filename):
base_dir = os.path.dirname(filename) base_dir = Path(filename).resolve().parent
YamlIncludeConstructor.add_to_loader_class( YamlIncludeConstructor.add_to_loader_class(
loader_class=yaml.FullLoader, base_dir=base_dir loader_class=yaml.FullLoader, base_dir=str(base_dir)
) )
with open(filename, "r", encoding="utf-8") as stream: with open(filename, "r", encoding="utf-8") as stream:

View file

@ -1,63 +0,0 @@
general:
frequency: "1m" # Run checks every minute.
# Which way do you want to be warned when a check goes to that severity?
alerts:
ok:
- local
warning:
- local
critical:
- local
unknown:
- local
# mail:
# mailfrom: no-reply@example.org
# host: 127.0.0.1
# port: 25
# ssl: False
# starttls: False
# auth:
# login: foo
# password: bar
# addresses:
# - foo@admin.example.org
# - bar@admin.example.org
# gotify:
# - url: https://example.org
# tokens:
# - foo
# - bar
service:
secrets:
# Secrets can be generated using `openssl rand -base64 32`.
ssl:
thresholds:
- "1d": critical
- "5d": warning
# It's also possible to define the checks in another file
# with the include syntax:
#
# websites: !include websites.yaml
#
websites:
- domain: "https://mypads.example.org"
paths:
- path: "/mypads/"
checks:
- status-is: 200
- body-contains: '<div id= "mypads"></div>'
- ssl-certificate-expiration: "on-check"
- path: "/admin/"
checks:
- status-is: 401
- domain: "https://munin.example.org"
paths:
- path: "/"
checks:
- status-is: 301
- path: "/munin/"
checks:
- status-is: 401

1
conf/config-example.yaml Symbolic link
View file

@ -0,0 +1 @@
../argos/config-example.yaml

View file

@ -30,10 +30,10 @@ pip install -e .
## Configure ## Configure
The quickest way to get started is to get the `config-example.yaml` file from our repository and edit it: The quickest way to get started is to generate the configuration file from argos and edit it:
```bash ```bash
wget https://framagit.org/framasoft/framaspace/argos/-/raw/main/conf/config-example.yaml -O config.yaml argos server generate-config > config.yaml
``` ```
You can read more about the configuration in the [configuration section](../configuration.md). You can read more about the configuration in the [configuration section](../configuration.md).