mirror of
https://framagit.org/framasoft/framaspace/argos.git
synced 2025-04-28 18:02:41 +02:00
✨ — Add new check type: status-in
Similar to status-is except that the HTTP status can be one of a list, instead of just one fixed value. Usecase: a Sympa server with CAS authentication set. Without a sympa_session cookie, you get a 302 status, with it, you have a 200 status.
This commit is contained in:
parent
9078a1384b
commit
fde061da19
7 changed files with 46 additions and 4 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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."""
|
||||||
|
|
||||||
|
|
|
@ -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 don’t mistyped it!
|
||||||
|
- status-in:
|
||||||
|
- 401
|
||||||
|
- 301
|
||||||
- domain: "https://munin.example.org"
|
- domain: "https://munin.example.org"
|
||||||
frequency: "20m"
|
frequency: "20m"
|
||||||
paths:
|
paths:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
Argos uses a simple YAML configuration file to define the server’s configuration, the websites to monitor and the checks to run on these websites.
|
Argos uses a simple YAML configuration file to define the server’s 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
|
||||||
|
|
Loading…
Reference in a new issue