🔀 Merge branch 'add-check/status-in' into 'develop'

 — Add new check type: status-in

See merge request framasoft/framaspace/argos!63
This commit is contained in:
Luc Didry 2024-07-04 13:50:15 +00:00
commit 77dbc8bb3a
7 changed files with 46 additions and 4 deletions

View file

@ -4,6 +4,7 @@
- 🩹 — Fix release documentation - 🩹 — Fix release documentation
- ✅ — Add mypy test - ✅ — Add mypy test
- ✨ — Add new check type: status-in
## 0.2.2 ## 0.2.2

View file

@ -54,7 +54,7 @@ class ArgosAgent:
while "forever": while "forever":
retry_now = await self._get_and_complete_tasks() retry_now = await self._get_and_complete_tasks()
if not retry_now: if not retry_now:
logger.error("Waiting %i seconds before next retry", self.wait_time) logger.info("Waiting %i seconds before next retry", self.wait_time)
await asyncio.sleep(self.wait_time) await asyncio.sleep(self.wait_time)
async def _complete_task(self, _task: dict) -> AgentResult: async def _complete_task(self, _task: dict) -> AgentResult:
@ -94,7 +94,7 @@ class ArgosAgent:
await self._post_results(results) await self._post_results(results)
return True return True
logger.error("Got no tasks from the server.") logger.info("Got no tasks from the server.")
return False return False
logger.error("Failed to fetch tasks: %s", response.read()) logger.error("Failed to fetch tasks: %s", response.read())
@ -110,7 +110,7 @@ class ArgosAgent:
) )
if response.status_code == httpx.codes.CREATED: if response.status_code == httpx.codes.CREATED:
logger.error( logger.info(
"Successfully posted results %s", json.dumps(response.json()) "Successfully posted results %s", json.dumps(response.json())
) )
else: else:

View file

@ -1,5 +1,6 @@
"""Define the available checks""" """Define the available checks"""
import json
from datetime import datetime from datetime import datetime
from argos.checks.base import ( from argos.checks.base import (
@ -31,6 +32,26 @@ class HTTPStatus(BaseCheck):
) )
class HTTPStatusIn(BaseCheck):
"""Checks that the HTTP status code is in the list of expected values."""
config = "status-in"
expected_cls = ExpectedStringValue
async def run(self) -> dict:
# XXX Get the method from the task
task = self.task
response = await self.http_client.request(
method="get", url=task.url, timeout=60
)
return self.response(
status=response.status_code in json.loads(self.expected),
expected=self.expected,
retrieved=response.status_code,
)
class HTTPBodyContains(BaseCheck): class HTTPBodyContains(BaseCheck):
"""Checks that the HTTP body contains the expected string.""" """Checks that the HTTP body contains the expected string."""

View file

@ -71,12 +71,19 @@ websites:
paths: paths:
- path: "/mypads/" - path: "/mypads/"
checks: checks:
# Check that the returned HTTP status is 200
- status-is: 200 - status-is: 200
# Check that the response contains this string
- body-contains: '<div id= "mypads"></div>' - body-contains: '<div id= "mypads"></div>'
# Check that the SSL certificate is no older than ssl.thresholds
- ssl-certificate-expiration: "on-check" - ssl-certificate-expiration: "on-check"
- path: "/admin/" - path: "/admin/"
checks: checks:
- status-is: 401 # Check that the return HTTP status is one of those
# Similar to status-is, verify that you dont mistyped it!
- status-in:
- 401
- 301
- domain: "https://munin.example.org" - domain: "https://munin.example.org"
frequency: "20m" frequency: "20m"
paths: paths:

View file

@ -2,6 +2,9 @@
For database models, see argos.server.models. For database models, see argos.server.models.
""" """
import json
from typing import Dict, List, Literal, Optional, Tuple from typing import Dict, List, Literal, Optional, Tuple
from pydantic import ( from pydantic import (
@ -78,6 +81,8 @@ def parse_checks(value):
raise ValueError(msg) raise ValueError(msg)
if isinstance(expected, int): if isinstance(expected, int):
expected = str(expected) expected = str(expected)
if isinstance(expected, list):
expected = json.dumps(expected)
return (name, expected) return (name, expected)

View file

@ -9,6 +9,7 @@ These checks are the most basic ones. They simply check that the response from t
| Check | Description | Configuration | | Check | Description | Configuration |
| --- | --- | --- | | --- | --- | --- |
| `status-is` | Check that the returned status code matches what you expect. | `status-is: "200"` | | `status-is` | Check that the returned status code matches what you expect. | `status-is: "200"` |
| `status-in` | Check that the returned status code is in the list of codes you expect. | <pre><code>status-in:<br> - 200<br> - 302</code></pre> |
| `body-contains` | Check that the returned body contains a given string. | `body-contains: "Hello world"` | | `body-contains` | Check that the returned body contains a given string. | `body-contains: "Hello world"` |
```{code-block} yaml ```{code-block} yaml
@ -21,6 +22,11 @@ caption: argos-config.yaml
checks: checks:
- status-is: 200 - status-is: 200
- body-contains: "Hello world" - body-contains: "Hello world"
- path: "/foobar"
checks:
- status-in:
- 200
- 302
``` ```
## SSL certificate expiration ## SSL certificate expiration

View file

@ -2,6 +2,8 @@
Argos uses a simple YAML configuration file to define the servers configuration, the websites to monitor and the checks to run on these websites. Argos uses a simple YAML configuration file to define the servers configuration, the websites to monitor and the checks to run on these websites.
See [here](checks.md) for more informations about the checks you can use.
Here is a simple self-documented configuration file, which you can get with [`argos server generate-config`](cli.md#server-generate-config): Here is a simple self-documented configuration file, which you can get with [`argos server generate-config`](cli.md#server-generate-config):
```{literalinclude} ../conf/config-example.yaml ```{literalinclude} ../conf/config-example.yaml