diff --git a/requirements.txt b/requirements.txt index e1fb467..4bd7ea5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,6 @@ +grafana-client==4.1.* opensearch-py==2.5.* prometheus-api-client==0.5.* -pytest-testinfra==10.1.* pylint==3.3.* +pytest-testinfra==10.1.* +requests==2.31.* diff --git a/stackhpc_cloud_tests/monitoring/__init__.py b/stackhpc_cloud_tests/monitoring/__init__.py new file mode 100644 index 0000000..0e8b8f8 --- /dev/null +++ b/stackhpc_cloud_tests/monitoring/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2024 StackHPC Ltd. + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. diff --git a/stackhpc_cloud_tests/monitoring/test_grafana.py b/stackhpc_cloud_tests/monitoring/test_grafana.py new file mode 100644 index 0000000..83c5b3d --- /dev/null +++ b/stackhpc_cloud_tests/monitoring/test_grafana.py @@ -0,0 +1,40 @@ +# Copyright (c) 2024 StackHPC Ltd. + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +# TODO: Check if we can validate that dashboards load correctly. + +from grafana_client import GrafanaApi +import os +import pytest + + +@pytest.fixture +def grafana() -> GrafanaApi: + """Pytest fixture that creates a Grafana API client.""" + # https://github.com/grafana-toolbox/grafana-client + grafana_url = os.environ["GRAFANA_URL"] + grafana_username = os.environ["GRAFANA_USERNAME"] + grafana_password = os.environ["GRAFANA_PASSWORD"] + return GrafanaApi.from_url( + grafana_url, + credential=(grafana_username, grafana_password), + ) + + +def test_grafana_api_stats(grafana): + """Test that Grafana API stats are accessible.""" + # https://grafana.com/docs/grafana/latest/developers/http_api/admin/#grafana-stats + result = grafana.admin.stats() + assert result["dashboards"] > 0 + assert result["datasources"] > 0 diff --git a/stackhpc_cloud_tests/test_opensearch.py b/stackhpc_cloud_tests/monitoring/test_opensearch.py similarity index 78% rename from stackhpc_cloud_tests/test_opensearch.py rename to stackhpc_cloud_tests/monitoring/test_opensearch.py index d57136a..caaa6c9 100644 --- a/stackhpc_cloud_tests/test_opensearch.py +++ b/stackhpc_cloud_tests/monitoring/test_opensearch.py @@ -13,12 +13,12 @@ # under the License. # TODO: -# * Dashboard login # * Cluster health from opensearchpy import OpenSearch import os import pytest +import requests from stackhpc_cloud_tests import utils @@ -60,3 +60,15 @@ def test_opensearch_has_info_logs(opensearch): # https://opensearch-project.github.io/opensearch-py/api-ref/clients/opensearch_client.html#opensearchpy.OpenSearch.search result = opensearch.search(body=query, index="flog-*", size=1) assert len(result["hits"]["hits"]) == 1 + + +def test_opensearch_dashboards_status(): + """Check that OpenSearch Dashboards is accessible and is in a green state.""" + dashboard_url = os.environ["OPENSEARCH_DASHBOARDS_URL"] + dashboard_username = os.environ["OPENSEARCH_DASHBOARDS_USERNAME"] + dashboard_password = os.environ["OPENSEARCH_DASHBOARDS_PASSWORD"] + dashboard_url += "/api/status" + result = requests.get(dashboard_url, auth=(dashboard_username, dashboard_password)) + assert result.ok + result = result.json() + assert result["status"]["overall"]["state"] == "green" diff --git a/stackhpc_cloud_tests/test_prometheus.py b/stackhpc_cloud_tests/monitoring/test_prometheus.py similarity index 72% rename from stackhpc_cloud_tests/test_prometheus.py rename to stackhpc_cloud_tests/monitoring/test_prometheus.py index 7478ffa..0b294b7 100644 --- a/stackhpc_cloud_tests/test_prometheus.py +++ b/stackhpc_cloud_tests/monitoring/test_prometheus.py @@ -39,3 +39,21 @@ def test_prometheus_node_exporter_metrics(prom): """Check that expected node exporter metrics exist.""" metrics = prom.all_metrics() assert "node_cpu_seconds_total" in metrics + + +def test_prometheus_alerts_inactive(prom): + """Check that no Prometheus alerts are active.""" + # https://prometheus.io/docs/prometheus/latest/querying/api/#alerts + response = prom._session.get( + "{0}/api/v1/alerts".format(prom.url), + verify=prom._session.verify, + headers=prom.headers, + auth=prom.auth, + cert=prom._session.cert, + ) + assert response.ok + response = response.json() + assert "status" in response + assert response["status"] == "success" + alerts = response["data"]["alerts"] + assert not alerts