mirror of
https://framagit.org/framasoft/framaspace/argos.git
synced 2025-04-28 18:02:41 +02:00
- Start implementing some tests using pytest - Packaged using pyproject.toml - Implemented SSL checks using httpx - Checks can now run partially on the server, to access the configuration and determine the severity of the error if any - Used black to format all the files - Added an utility to convert strings like "3d" and "3w" to days - The internal representation of SSL thresholds is now a list of tuples - Models were lacking some relationship between Tasks and Results
88 lines
2.8 KiB
Python
88 lines
2.8 KiB
Python
from fastapi import Depends, FastAPI, HTTPException, Request
|
|
from sqlalchemy.orm import Session
|
|
from pydantic import BaseModel, ValidationError
|
|
import sys
|
|
|
|
from argos.server import queries, models
|
|
from argos.schemas import AgentResult, Task
|
|
from argos.schemas.config import from_yaml as get_schemas_from_yaml
|
|
from argos.server.database import SessionLocal, engine
|
|
from argos.checks import get_check_by_name
|
|
from argos.logging import logger
|
|
from typing import List
|
|
|
|
models.Base.metadata.create_all(bind=engine)
|
|
|
|
app = FastAPI()
|
|
|
|
|
|
def get_db():
|
|
db = SessionLocal()
|
|
try:
|
|
yield db
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
@app.on_event("startup")
|
|
async def read_config_and_populate_db():
|
|
# XXX Get filename from environment.
|
|
try:
|
|
config = get_schemas_from_yaml("config.yaml")
|
|
app.config = config
|
|
except ValidationError as e:
|
|
logger.error(f"Errors where found while reading configuration:")
|
|
for error in e.errors():
|
|
logger.error(f"{error['loc']} is {error['type']}")
|
|
sys.exit(1)
|
|
|
|
db = SessionLocal()
|
|
try:
|
|
await queries.update_from_config(db, config)
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
# XXX Get the default limit from the config
|
|
@app.get("/tasks", response_model=list[Task])
|
|
async def read_tasks(request: Request, limit: int = 20, db: Session = Depends(get_db)):
|
|
# XXX Let the agents specifify their names (and use hostnames)
|
|
tasks = await queries.list_tasks(db, agent_id=request.client.host, limit=limit)
|
|
return tasks
|
|
|
|
|
|
@app.post("/results", status_code=201)
|
|
async def create_result(results: List[AgentResult], db: Session = Depends(get_db)):
|
|
"""Get the results from the agents and store them locally.
|
|
|
|
- Finalize the checks (some checks need the server to do some part of the validation,
|
|
for instance because they need access to the configuration)
|
|
- If it's an error, determine its severity ;
|
|
- Trigger the reporting calls
|
|
"""
|
|
db_results = []
|
|
for agent_result in results:
|
|
result = await queries.create_result(db, agent_result)
|
|
# XXX Maybe offload this to a queue.
|
|
# XXX Use a schema for the on-check value.
|
|
|
|
if result.status == "on-check":
|
|
task = await queries.get_task(db, agent_result.task_id)
|
|
if not task:
|
|
logger.error(f"Unable to find task {agent_result.task_id}")
|
|
else:
|
|
check = task.get_check()
|
|
callback = logger.error
|
|
await check.finalize(app.config, callback=callback, **result.context)
|
|
|
|
db_results.append(result)
|
|
db.commit()
|
|
return {"result_ids": [r.id for r in db_results]}
|
|
|
|
|
|
@app.get("/stats")
|
|
async def get_stats(db: Session = Depends(get_db)):
|
|
return {
|
|
"tasks_count": await queries.count_tasks(db),
|
|
"results_count": await queries.count_results(db),
|
|
}
|