mirror of
https://framagit.org/framasoft/framaspace/argos.git
synced 2025-04-28 18:02:41 +02:00
🔀 Merge branch 'fix-57' into develop
This commit is contained in:
commit
67162f6ce4
5 changed files with 121 additions and 2 deletions
|
@ -6,10 +6,11 @@
|
||||||
- ✅ — Add mypy test
|
- ✅ — Add mypy test
|
||||||
- ✨ — Add new check type: status-in
|
- ✨ — Add new check type: status-in
|
||||||
- 🩹 — Close menu after rescheduling non-ok checks (#55)
|
- 🩹 — Close menu after rescheduling non-ok checks (#55)
|
||||||
- ✨ — Add new check types: headers-contain and headers-have
|
- ✨ — Add new check types: headers-contain and headers-have (#56)
|
||||||
- ✨ — Add command to test email configuration (!66)
|
- ✨ — Add command to test email configuration (!66)
|
||||||
- 💄 — Enhance the mobile view (!67)
|
- 💄 — Enhance the mobile view (!67)
|
||||||
- ✨ — Allow to run Argos in a subfolder (i.e. not on /) (#59)
|
- ✨ — Allow to run Argos in a subfolder (i.e. not on /) (#59)
|
||||||
|
- ✨ — Add new check types: json-contains, json-has and json-is (#57)
|
||||||
|
|
||||||
## 0.2.2
|
## 0.2.2
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from jsonpointer import resolve_pointer, JsonPointerException
|
||||||
|
|
||||||
from argos.checks.base import (
|
from argos.checks.base import (
|
||||||
BaseCheck,
|
BaseCheck,
|
||||||
ExpectedIntValue,
|
ExpectedIntValue,
|
||||||
|
@ -121,6 +123,94 @@ class HTTPBodyContains(BaseCheck):
|
||||||
return self.response(status=self.expected in response.text)
|
return self.response(status=self.expected in response.text)
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPJsonContains(BaseCheck):
|
||||||
|
"""Checks that JSON response contains the expected structure
|
||||||
|
(without checking the value)"""
|
||||||
|
|
||||||
|
config = "json-contains"
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
obj = response.json()
|
||||||
|
|
||||||
|
status = True
|
||||||
|
for pointer in json.loads(self.expected):
|
||||||
|
try:
|
||||||
|
resolve_pointer(obj, pointer)
|
||||||
|
except JsonPointerException:
|
||||||
|
status = False
|
||||||
|
break
|
||||||
|
|
||||||
|
return self.response(
|
||||||
|
status=status,
|
||||||
|
expected=self.expected,
|
||||||
|
retrieved=json.dumps(obj),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPJsonHas(BaseCheck):
|
||||||
|
"""Checks that JSON response contains the expected structure and values"""
|
||||||
|
|
||||||
|
config = "json-has"
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
obj = response.json()
|
||||||
|
|
||||||
|
status = True
|
||||||
|
for pointer, exp_value in json.loads(self.expected).items():
|
||||||
|
try:
|
||||||
|
value = resolve_pointer(obj, pointer)
|
||||||
|
if value != exp_value:
|
||||||
|
status = False
|
||||||
|
break
|
||||||
|
except JsonPointerException:
|
||||||
|
status = False
|
||||||
|
break
|
||||||
|
|
||||||
|
return self.response(
|
||||||
|
status=status,
|
||||||
|
expected=self.expected,
|
||||||
|
retrieved=json.dumps(obj),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPJsonIs(BaseCheck):
|
||||||
|
"""Checks that JSON response is the exact expected JSON object"""
|
||||||
|
|
||||||
|
config = "json-is"
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
obj = response.json()
|
||||||
|
|
||||||
|
status = response.json() == json.loads(self.expected)
|
||||||
|
|
||||||
|
return self.response(
|
||||||
|
status=status,
|
||||||
|
expected=self.expected,
|
||||||
|
retrieved=json.dumps(obj),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SSLCertificateExpiration(BaseCheck):
|
class SSLCertificateExpiration(BaseCheck):
|
||||||
"""Checks that the SSL certificate will not expire soon."""
|
"""Checks that the SSL certificate will not expire soon."""
|
||||||
|
|
||||||
|
|
|
@ -99,10 +99,26 @@ websites:
|
||||||
- 401
|
- 401
|
||||||
- 301
|
- 301
|
||||||
# Check that the response contains this headers and values
|
# Check that the response contains this headers and values
|
||||||
|
# It’s VERY important to respect the 4 spaces indentation here!
|
||||||
# The name of the headers is case insensitive
|
# The name of the headers is case insensitive
|
||||||
- headers-have:
|
- headers-have:
|
||||||
content-encoding: "gzip"
|
content-encoding: "gzip"
|
||||||
content-type: "text/html"
|
content-type: "text/html"
|
||||||
|
- path: "/my-stats.json"
|
||||||
|
checks:
|
||||||
|
# Check that JSON response contains the expected structure
|
||||||
|
- json-contains:
|
||||||
|
- /foo/bar/0
|
||||||
|
- /foo/bar/1
|
||||||
|
- /timestamp
|
||||||
|
# Check that JSON response contains the expected structure and values
|
||||||
|
# It’s VERY important to respect the 4 spaces indentation here!
|
||||||
|
- json-has:
|
||||||
|
/maintenance: false
|
||||||
|
/productname: "Nextcloud"
|
||||||
|
# Check that JSON response is the exact expected JSON object
|
||||||
|
# The order of the items in the object does not matter.
|
||||||
|
- json-is: '{"foo": "bar", "baz": 42}'
|
||||||
- domain: "https://munin.example.org"
|
- domain: "https://munin.example.org"
|
||||||
frequency: "20m"
|
frequency: "20m"
|
||||||
paths:
|
paths:
|
||||||
|
|
|
@ -12,7 +12,10 @@ These checks are the most basic ones. They simply check that the response from t
|
||||||
| `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> |
|
| `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"` |
|
||||||
| `headers-contain` | Check that the response contains the expected headers. | <pre><code>headers-contain:<br> - "content-encoding"<br> - "content-type"</code></pre> |
|
| `headers-contain` | Check that the response contains the expected headers. | <pre><code>headers-contain:<br> - "content-encoding"<br> - "content-type"</code></pre> |
|
||||||
| `headers-have` | Check that the response contains the expected headers. | <pre><code>headers-have:<br> content-encoding: "gzip"<br> content-type: "text/html"</code></pre> |
|
| `headers-have` | Check that the response contains the expected headers with the expected value. | <pre><code>headers-have:<br> content-encoding: "gzip"<br> content-type: "text/html"</code></pre> |
|
||||||
|
| `json-contains` | Check that JSON response contains the expected structure. | <pre><code>json-contains:<br> - /foo/bar/0<br> - /timestamp</code></pre> |
|
||||||
|
| `json-has` | Check that JSON response contains the expected structure and values. | <pre><code>json-has:<br> /maintenance: false<br> /productname: "Nextcloud"</code></pre> |
|
||||||
|
| `json-is` | Check that JSON response is the exact expected JSON object | `json-is: '{"foo": "bar", "baz": 42}'`|
|
||||||
|
|
||||||
```{code-block} yaml
|
```{code-block} yaml
|
||||||
---
|
---
|
||||||
|
@ -36,6 +39,14 @@ caption: argos-config.yaml
|
||||||
- headers-have:
|
- headers-have:
|
||||||
content-encoding: "gzip"
|
content-encoding: "gzip"
|
||||||
content-type: "text/html"
|
content-type: "text/html"
|
||||||
|
- json-contains:
|
||||||
|
- /foo/bar/0
|
||||||
|
- /timestamp
|
||||||
|
# It’s VERY important to respect the 4 spaces indentation here!
|
||||||
|
- json-has:
|
||||||
|
/maintenance: false
|
||||||
|
/productname: "Nextcloud"
|
||||||
|
- json-is: '{"foo": "bar", "baz": 42}'
|
||||||
```
|
```
|
||||||
|
|
||||||
## SSL certificate expiration
|
## SSL certificate expiration
|
||||||
|
|
|
@ -28,6 +28,7 @@ dependencies = [
|
||||||
"fastapi-login>=1.10.0,<2",
|
"fastapi-login>=1.10.0,<2",
|
||||||
"httpx>=0.25,<0.27.0",
|
"httpx>=0.25,<0.27.0",
|
||||||
"Jinja2>=3.0,<4",
|
"Jinja2>=3.0,<4",
|
||||||
|
"jsonpointer>=3.0,<4",
|
||||||
"passlib>=1.7.4,<2",
|
"passlib>=1.7.4,<2",
|
||||||
"psycopg2-binary>=2.9,<3",
|
"psycopg2-binary>=2.9,<3",
|
||||||
"pydantic[email]>=2.4,<3",
|
"pydantic[email]>=2.4,<3",
|
||||||
|
|
Loading…
Reference in a new issue