Support !include filename in the yaml files.

- run isort on the codebase
This commit is contained in:
Alexis Métaireau 2023-10-10 11:45:33 +02:00
parent cdfb1e30ac
commit d35be89f4b
17 changed files with 76 additions and 132 deletions

View file

@ -15,6 +15,7 @@ sqlalchemy = {extras = ["asyncio"] }
pyopenssl = "*" pyopenssl = "*"
ipdb = "*" ipdb = "*"
argos = {extras = ["dev"], file = ".", editable = true} argos = {extras = ["dev"], file = ".", editable = true}
pyyaml-include = "*"
[dev-packages] [dev-packages]

11
Pipfile.lock generated
View file

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "545ec239a057ec56cb3b4e5d7d6b8922a837d9ce2340e4b2def368c8064acf73" "sha256": "8cc9237ff86d00019539f36e3df5b20edcbbc60f52d1b0fce2b03e51c089ad39"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -669,6 +669,15 @@
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==6.0.1" "version": "==6.0.1"
}, },
"pyyaml-include": {
"hashes": [
"sha256:4cb3b4e1baae2ec251808fe1e8aed5d3d20699c541864c8e47ed866ab2f15039",
"sha256:e58525721a2938d29c4046350f8aad86f848660a770c29605e6f2700925fa753"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==1.3.1"
},
"six": { "six": {
"hashes": [ "hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",

View file

@ -1,10 +1,11 @@
import httpx
import asyncio import asyncio
from typing import List from typing import List
from argos.logging import logger
from argos.checks import CheckNotFound, get_registered_check
from argos.schemas import Task, AgentResult, SerializableException import httpx
from argos.checks import CheckNotFound, get_registered_check
from argos.logging import logger
from argos.schemas import AgentResult, SerializableException, Task
async def complete_task(http_client: httpx.AsyncClient, task: dict) -> dict: async def complete_task(http_client: httpx.AsyncClient, task: dict) -> dict:
@ -58,4 +59,4 @@ async def run_agent(server: str, auth: str, max_tasks: int):
# Post the results # Post the results
await post_results(http_client, server, results) await post_results(http_client, server, results)
else: else:
logger.error(f"Failed to fetch tasks: {response.read()}") logger.error(f"Failed to fetch tasks: {response.read()}")

View file

@ -1,2 +1,4 @@
from argos.checks.checks import HTTPStatus, HTTPBodyContains, SSLCertificateExpiration from argos.checks.base import (CheckNotFound, get_registered_check,
from argos.checks.base import get_registered_checks, get_registered_check, CheckNotFound get_registered_checks)
from argos.checks.checks import (HTTPBodyContains, HTTPStatus,
SSLCertificateExpiration)

View file

@ -1,8 +1,8 @@
from pydantic import BaseModel, Field
from dataclasses import dataclass from dataclasses import dataclass
from typing import Type from typing import Type
import httpx import httpx
from pydantic import BaseModel, Field
from argos.schemas import Task from argos.schemas import Task

View file

@ -1,17 +1,13 @@
from argos.logging import logger
from argos.checks.base import (
BaseCheck,
Response,
Status,
ExpectedIntValue,
ExpectedStringValue,
)
import ssl import ssl
import time import time
from datetime import datetime from datetime import datetime
from OpenSSL import crypto from OpenSSL import crypto
from argos.checks.base import (BaseCheck, ExpectedIntValue,
ExpectedStringValue, Response, Status)
from argos.logging import logger
class HTTPStatus(BaseCheck): class HTTPStatus(BaseCheck):
config = "status-is" config = "status-is"

View file

@ -1,15 +1,18 @@
import click
import subprocess
import asyncio import asyncio
import subprocess
import click
from argos.agent import run_agent
from argos import logging from argos import logging
from argos.agent import run_agent
from argos.logging import logger from argos.logging import logger
@click.group() @click.group()
def cli(): def cli():
pass pass
@cli.command() @cli.command()
@click.option("--server", required=True, help="Server URL") @click.option("--server", required=True, help="Server URL")
@click.option("--auth", required=True, help="The authentication token") @click.option("--auth", required=True, help="The authentication token")
@ -36,5 +39,6 @@ def server(host, port, reload):
command.append("--reload") command.append("--reload")
subprocess.run(command) subprocess.run(command)
if __name__ == "__main__": if __name__ == "__main__":
cli() cli()

View file

@ -1,14 +1,11 @@
from pydantic import BaseModel import os
from datetime import datetime
from enum import StrEnum from enum import StrEnum
from typing import List, Optional, Tuple, Literal from typing import Dict, List, Literal, Optional, Tuple, Union
from typing import Dict, Union, List
import yaml import yaml
from pydantic import BaseModel, Field, HttpUrl, validator from pydantic import BaseModel, Field, HttpUrl, validator
from yamlinclude import YamlIncludeConstructor
from datetime import datetime
# XXX Find a way to check without having cirular imports # XXX Find a way to check without having cirular imports
@ -66,7 +63,8 @@ class WebsitePath(BaseModel):
@validator("checks", each_item=True, pre=True) @validator("checks", each_item=True, pre=True)
def parse_checks(cls, value): def parse_checks(cls, value):
from argos.checks import get_registered_checks # To avoid circular imports from argos.checks import \
get_registered_checks # To avoid circular imports
available_names = get_registered_checks().keys() available_names = get_registered_checks().keys()
@ -109,11 +107,16 @@ def validate_config(config: dict):
return Config(**config) return Config(**config)
def from_yaml(file_name): def from_yaml(filename):
parsed = load_yaml(file_name) parsed = load_yaml(filename)
return validate_config(parsed) return validate_config(parsed)
def load_yaml(file_name): def load_yaml(filename):
with open(file_name, "r") as stream: base_dir = os.path.dirname(filename)
return yaml.safe_load(stream) YamlIncludeConstructor.add_to_loader_class(
loader_class=yaml.FullLoader, base_dir=base_dir
)
with open(filename, "r") as stream:
return yaml.load(stream, Loader=yaml.FullLoader)

View file

@ -1,7 +1,8 @@
from pydantic import BaseModel import traceback
from datetime import datetime from datetime import datetime
from typing import Literal from typing import Literal
import traceback
from pydantic import BaseModel
# XXX Refactor using SQLModel to avoid duplication of model data # XXX Refactor using SQLModel to avoid duplication of model data

View file

@ -1,8 +1,8 @@
import sys import sys
from typing import Annotated, List, Optional from typing import Annotated, List, Optional
from fastapi import Depends, FastAPI, HTTPException, Request, Header from fastapi import Depends, FastAPI, Header, HTTPException, Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from pydantic import BaseModel, ValidationError from pydantic import BaseModel, ValidationError
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@ -60,7 +60,7 @@ async def read_tasks(request: Request, db: Session = Depends(get_db), limit: int
return tasks return tasks
@app.post("/results", status_code=201) @app.post("/results", status_code=201, dependencies=[Depends(verify_token)])
async def create_result(results: List[AgentResult], db: Session = Depends(get_db)): async def create_result(results: List[AgentResult], db: Session = Depends(get_db)):
"""Get the results from the agents and store them locally. """Get the results from the agents and store them locally.
@ -89,7 +89,7 @@ async def create_result(results: List[AgentResult], db: Session = Depends(get_db
return {"result_ids": [r.id for r in db_results]} return {"result_ids": [r.id for r in db_results]}
@app.get("/stats") @app.get("/stats", dependencies=[Depends(verify_token)])
async def get_stats(db: Session = Depends(get_db)): async def get_stats(db: Session = Depends(get_db)):
return { return {
"tasks_count": await queries.count_tasks(db), "tasks_count": await queries.count_tasks(db),

View file

@ -1,8 +1,6 @@
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import DeclarativeBase, sessionmaker
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
SQLALCHEMY_DATABASE_URL = "sqlite:////tmp/argos.db" SQLALCHEMY_DATABASE_URL = "sqlite:////tmp/argos.db"
# SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db" # SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"

View file

@ -1,22 +1,13 @@
from typing import List, Literal
from sqlalchemy import (
Boolean,
Column,
ForeignKey,
Integer,
String,
JSON,
DateTime,
Enum,
)
from sqlalchemy.orm import relationship, Mapped, mapped_column, DeclarativeBase
from sqlalchemy_utils import ChoiceType
from sqlalchemy.orm import mapped_column, relationship
from datetime import datetime from datetime import datetime
from typing import List, Literal
from sqlalchemy import (JSON, Boolean, Column, DateTime, Enum, ForeignKey,
Integer, String)
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
from sqlalchemy_utils import ChoiceType
from argos.schemas import WebsiteCheck
from argos.checks import get_registered_check from argos.checks import get_registered_check
from argos.schemas import WebsiteCheck
class Base(DeclarativeBase): class Base(DeclarativeBase):

View file

@ -1,12 +1,12 @@
from sqlalchemy.orm import Session from datetime import datetime
from urllib.parse import urljoin
from sqlalchemy import exists from sqlalchemy import exists
from sqlalchemy.orm import Session
from argos import schemas from argos import schemas
from argos.logging import logger from argos.logging import logger
from argos.server.models import Task, Result from argos.server.models import Result, Task
from urllib.parse import urljoin
from datetime import datetime
async def list_tasks(db: Session, agent_id: str, limit: int = 100): async def list_tasks(db: Session, agent_id: str, limit: int = 100):

View file

@ -19,69 +19,4 @@ ssl:
- "1d": critical - "1d": critical
"5d": warning "5d": warning
websites: websites: !include websites.yaml
- domain: "https://mypads.framapad.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.framasoft.org"
paths:
- path: "/"
checks:
- status-is: 301
- path: "/munin/"
checks:
- status-is: 401
- domain: "https://framagenda.org"
paths:
- path: "/status.php"
checks:
- status-is: 200
# Là, idéalement, il faudrait un json-contains,
# qui serait une table de hachage
- body-contains: '"maintenance":false'
- ssl-certificate-expiration: "on-check"
- path: "/"
checks:
- status-is: 302
- path: "/login"
checks:
- status-is: 200
- domain: "https://framadrive.org"
paths:
- path: "/status.php"
checks:
- status-is: 200
- body-contains: '"maintenance":false'
- ssl-certificate-expiration: "on-check"
- path: "/"
checks:
- status-is: 302
- path: "/login"
checks:
- status-is: 200
- domain: "https://cloud.framabook.org"
paths:
- path: "/status.php"
checks:
- status-is: 200
- body-contains: '"maintenance":false'
- ssl-certificate-expiration: "on-check"
- path: "/"
checks:
- status-is: 302
- path: "/login"
checks:
- status-is: 200
- domain: "https://framasoft.org"
paths:
- path: "/"
checks:
- status-is: 200
- ssl-certificate-expiration: "on-check"

View file

@ -22,6 +22,7 @@ dependencies = [
"httpx>=0.25,<1", "httpx>=0.25,<1",
"pydantic>=2.4,<3", "pydantic>=2.4,<3",
"pyyaml>=6.0,<7", "pyyaml>=6.0,<7",
"pyyaml-include>=1.3,<2",
"sqlalchemy[asyncio]>=2.0,<3", "sqlalchemy[asyncio]>=2.0,<3",
"sqlalchemy-utils>=0.41,<1", "sqlalchemy-utils>=0.41,<1",
"uvicorn>=0.23,<1", "uvicorn>=0.23,<1",

View file

@ -1,4 +1,5 @@
import pytest import pytest
from argos.checks.base import Response, Status from argos.checks.base import Response, Status

View file

@ -1,4 +1,5 @@
import pytest import pytest
from argos.schemas.config import SSL, WebsitePath from argos.schemas.config import SSL, WebsitePath