Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Docker and SELinux tests #4

Draft
wants to merge 4 commits into
base: opensearch-dashboards-grafana
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
grafana-client==4.1.*
opensearch-py==2.5.*
packaging==24.*
prometheus-api-client==0.5.*
pytest-subtests==0.12.*
pytest-testinfra==10.1.*
requests==2.31.*
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = stackhpc-openstack-tests
version = 0.1.0
version = 0.0.2
summary = Automated testing for StackHPC OpenStack
description-file = README.md
author = Mark Goddard
Expand Down
13 changes: 13 additions & 0 deletions stackhpc_openstack_tests/host/__init__.py
Original file line number Diff line number Diff line change
@@ -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.
97 changes: 97 additions & 0 deletions stackhpc_openstack_tests/host/test_docker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# 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.

import json
import os
from packaging.version import parse
import pytest


@pytest.fixture
def docker_info(host, scope="session"):
"""Pytest fixture that provides the output of 'docker info'."""
with host.sudo("stack"):
docker_info = host.check_output("docker info --format json")
return json.loads(docker_info)


def test_docker_version(host):
"""Check that Docker is accessible and optionally check version."""
# An optional inclusive minimum version.
min_version = os.environ.get("DOCKER_VERSION_MIN")
# An optional exclusive maximum version.
max_version = os.environ.get("DOCKER_VERSION_MAX")
with host.sudo("stack"):
client_version = parse(host.docker.client_version())
server_version = parse(host.docker.server_version())
if min_version:
min_version = parse(min_version)
assert client_version >= min_version
assert server_version >= min_version
if max_version:
max_version = parse(max_version)
assert client_version < max_version
assert server_version < max_version


def test_docker_containers(subtests, host):
"""Check that Docker containers are healthy."""
with host.sudo("stack"):
docker_containers = host.docker.get_containers()
for container in docker_containers:
# Use the subtests fixture to create a dynamically parametrised test
# based on the containers on the system.
with subtests.test(msg="container=" + container.name):
state = container.inspect()["State"]
assert state["Running"]
assert not state["Restarting"]
assert not state["Dead"]
assert not state["OOMKilled"]
if "Health" in state:
assert state["Health"]["Status"] == "healthy"
if "HostConfig" in state:
assert state["HostConfig"]["LogConfig"]["Type"] == "json-file"
assert "max-file" in state["HostConfig"]["LogConfig"]["Config"]
assert "max-size" in state["HostConfig"]["LogConfig"]["Config"]


def test_docker_driver(docker_info):
"""Check that Docker is using the overlay2 storage driver."""
assert docker_info["Driver"] == "overlay2"


def test_no_bridge_network_exists(host):
"""Check that no bridge network exists."""
with host.sudo("stack"):
docker_networks = host.check_output("docker network ls --format json")
for network in docker_networks.splitlines():
network = json.loads(network)
assert network["Name"] != "bridge"
assert network["Driver"] != "bridge"


def test_ip_forwarding_disabled(docker_info):
"""Check that IP forwarding is disabled."""
assert not docker_info["IPv4Forwarding"]


def test_iptables_disabled(docker_info):
"""Check that IPTables manipulation is disabled."""
assert not docker_info["BridgeNfIptables"]
assert not docker_info["BridgeNfIp6tables"]


def test_live_restore_enabled(docker_info):
"""Check that live restore is enabled."""
assert docker_info["LiveRestoreEnabled"]
38 changes: 38 additions & 0 deletions stackhpc_openstack_tests/host/test_selinux.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 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.

import os
import pytest


def test_selinux(host):
"""Check that SELinux is enabled and permissive on supported systems."""
# Adapted from Kayobe host configure tests:
# https://opendev.org/openstack/kayobe/src/branch/master/playbooks/kayobe-overcloud-host-configure-base/tests/test_overcloud_host_configure.py
if host.system_info.distribution in {"debian", "ubuntu"}:
pytest.skip(reason="SELinux is not supported on Debian or Ubuntu")
# Desired state: enforcing, permissive or disabled
expected_state = os.environ["SELINUX_STATE"]
assert expected_state in {"enforcing", "permissive", "disabled"}
expected_status = "disabled" if expected_state == "disabled" else "enabled"
expected_mode = expected_state
selinux = host.check_output("sestatus")
selinux = selinux.splitlines()
# Remove duplicate whitespace characters in output
selinux = [" ".join(x.split()) for x in selinux]

assert f"SELinux status: {expected_status}" in selinux
if expected_status == "enabled":
assert f"Current mode: {expected_mode}" in selinux
assert f"Mode from config file: {expected_mode}" in selinux
6 changes: 5 additions & 1 deletion stackhpc_openstack_tests/monitoring/test_opensearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ def test_opensearch_dashboards_status():
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))
dashboard_cacert = os.environ.get("OPENSEARCH_DASHBOARDS_CACERT")
kwargs = {}
if dashboard_cacert:
kwargs["verify"] = dashboard_cacert
result = requests.get(dashboard_url, auth=(dashboard_username, dashboard_password), **kwargs)
assert result.ok
result = result.json()
assert result["status"]["overall"]["state"] == "green"