mirror of
https://framagit.org/framasoft/framaspace/argos.git
synced 2025-04-28 18:02:41 +02:00
🔀 Merge branch 'fix-56' into 'develop'
✨ — Add new check types: headers-contain and headers-have (fix #56) See merge request framasoft/framaspace/argos!65
This commit is contained in:
commit
7eede341e4
5 changed files with 90 additions and 8 deletions
|
@ -6,6 +6,7 @@
|
||||||
- ✅ — 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
|
||||||
|
|
||||||
## 0.2.2
|
## 0.2.2
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,62 @@ class HTTPStatusIn(BaseCheck):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPHeadersContain(BaseCheck):
|
||||||
|
"""Checks that response headers contains the expected headers
|
||||||
|
(without checking their values)"""
|
||||||
|
|
||||||
|
config = "headers-contain"
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
status = True
|
||||||
|
for header in json.loads(self.expected):
|
||||||
|
if header not in response.headers:
|
||||||
|
status = False
|
||||||
|
break
|
||||||
|
|
||||||
|
return self.response(
|
||||||
|
status=status,
|
||||||
|
expected=self.expected,
|
||||||
|
retrieved=json.dumps(list(dict(response.headers).keys())),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPHeadersHave(BaseCheck):
|
||||||
|
"""Checks that response headers contains the expected headers and values"""
|
||||||
|
|
||||||
|
config = "headers-have"
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
status = True
|
||||||
|
for header, value in json.loads(self.expected).items():
|
||||||
|
if header not in response.headers:
|
||||||
|
status = False
|
||||||
|
break
|
||||||
|
if response.headers[header] != value:
|
||||||
|
status = False
|
||||||
|
break
|
||||||
|
|
||||||
|
return self.response(
|
||||||
|
status=status,
|
||||||
|
expected=self.expected,
|
||||||
|
retrieved=json.dumps(dict(response.headers)),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class HTTPBodyContains(BaseCheck):
|
class HTTPBodyContains(BaseCheck):
|
||||||
"""Checks that the HTTP body contains the expected string."""
|
"""Checks that the HTTP body contains the expected string."""
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
---
|
||||||
general:
|
general:
|
||||||
db:
|
db:
|
||||||
# The database URL, as defined in SQLAlchemy docs : https://docs.sqlalchemy.org/en/20/core/engines.html#database-urls
|
# The database URL, as defined in SQLAlchemy docs :
|
||||||
|
# https://docs.sqlalchemy.org/en/20/core/engines.html#database-urls
|
||||||
# Example for SQLite: "sqlite:////tmp/argos.db"
|
# Example for SQLite: "sqlite:////tmp/argos.db"
|
||||||
url: "postgresql://argos:argos@localhost/argos"
|
url: "postgresql://argos:argos@localhost/argos"
|
||||||
# You configure the size of the database pool of connection, and the max overflow (until when new connections are accepted ?)
|
# You configure the size of the database pool of connection, and
|
||||||
# See https://docs.sqlalchemy.org/en/20/core/pooling.html#sqlalchemy.pool.QueuePool.params.pool_size for details
|
# the max overflow (until when new connections are accepted ?)
|
||||||
|
# For details, see
|
||||||
|
# https://docs.sqlalchemy.org/en/20/core/pooling.html#sqlalchemy.pool.QueuePool.params.pool_size
|
||||||
pool_size: 10
|
pool_size: 10
|
||||||
max_overflow: 20
|
max_overflow: 20
|
||||||
# Can be "production", "dev", "test".
|
# Can be "production", "dev", "test".
|
||||||
|
@ -77,13 +81,23 @@ websites:
|
||||||
- body-contains: '<div id= "mypads"></div>'
|
- body-contains: '<div id= "mypads"></div>'
|
||||||
# Check that the SSL certificate is no older than ssl.thresholds
|
# Check that the SSL certificate is no older than ssl.thresholds
|
||||||
- ssl-certificate-expiration: "on-check"
|
- ssl-certificate-expiration: "on-check"
|
||||||
|
# Check that the response contains this headers
|
||||||
|
# The comparison is case insensitive
|
||||||
|
- headers-contain:
|
||||||
|
- "content-encoding"
|
||||||
|
- "content-type"
|
||||||
- path: "/admin/"
|
- path: "/admin/"
|
||||||
checks:
|
checks:
|
||||||
# Check that the return HTTP status is one of those
|
# Check that the return HTTP status is one of those
|
||||||
# Similar to status-is, verify that you don’t mistyped it!
|
# Similar to status-is, verify that you don’t mistyped it!
|
||||||
- status-in:
|
- status-in:
|
||||||
- 401
|
- 401
|
||||||
- 301
|
- 301
|
||||||
|
# Check that the response contains this headers and values
|
||||||
|
# The name of the headers is case insensitive
|
||||||
|
- headers-have:
|
||||||
|
content-encoding: "gzip"
|
||||||
|
content-type: "text/html"
|
||||||
- domain: "https://munin.example.org"
|
- domain: "https://munin.example.org"
|
||||||
frequency: "20m"
|
frequency: "20m"
|
||||||
paths:
|
paths:
|
||||||
|
|
|
@ -83,6 +83,8 @@ def parse_checks(value):
|
||||||
expected = str(expected)
|
expected = str(expected)
|
||||||
if isinstance(expected, list):
|
if isinstance(expected, list):
|
||||||
expected = json.dumps(expected)
|
expected = json.dumps(expected)
|
||||||
|
if isinstance(expected, dict):
|
||||||
|
expected = json.dumps(expected)
|
||||||
return (name, expected)
|
return (name, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,10 @@ 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> |
|
| `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-have` | Check that the response contains the expected headers. | <pre><code>headers-have:<br> content-encoding: "gzip"<br> content-type: "text/html"</code></pre> |
|
||||||
|
|
||||||
```{code-block} yaml
|
```{code-block} yaml
|
||||||
---
|
---
|
||||||
|
@ -22,11 +24,18 @@ caption: argos-config.yaml
|
||||||
checks:
|
checks:
|
||||||
- status-is: 200
|
- status-is: 200
|
||||||
- body-contains: "Hello world"
|
- body-contains: "Hello world"
|
||||||
|
- headers-contain:
|
||||||
|
- "content-encoding"
|
||||||
|
- "content-type"
|
||||||
- path: "/foobar"
|
- path: "/foobar"
|
||||||
checks:
|
checks:
|
||||||
- status-in:
|
- status-in:
|
||||||
- 200
|
- 200
|
||||||
- 302
|
- 302
|
||||||
|
# It’s VERY important to respect the 4 spaces indentation here!
|
||||||
|
- headers-have:
|
||||||
|
content-encoding: "gzip"
|
||||||
|
content-type: "text/html"
|
||||||
```
|
```
|
||||||
|
|
||||||
## SSL certificate expiration
|
## SSL certificate expiration
|
||||||
|
|
Loading…
Reference in a new issue