Skip to content

Commit 0ef02ef

Browse files
committed
Add initial Docker tests
Adds a new host module to include Docker and other host-level tests that will use testinfra.
1 parent f5fa6ae commit 0ef02ef

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
grafana-client==4.1.*
22
opensearch-py==2.5.*
3+
packaging==24.*
34
prometheus-api-client==0.5.*
5+
pytest-subtests==0.12.*
46
pytest-testinfra==10.1.*
57
requests==2.31.*
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright (c) 2024 StackHPC Ltd.
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Copyright (c) 2024 StackHPC Ltd.
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
import json
16+
import os
17+
from packaging.version import parse
18+
import pytest
19+
20+
21+
@pytest.fixture
22+
def docker_info(host, scope="session"):
23+
"""Pytest fixture that provides the output of 'docker info'."""
24+
with host.sudo("stack"):
25+
docker_info = host.check_output("docker info --format json")
26+
return json.loads(docker_info)
27+
28+
29+
def test_docker_version(host):
30+
"""Check that Docker is accessible and optionally check version."""
31+
# An optional inclusive minimum version.
32+
min_version = os.environ.get("DOCKER_VERSION_MIN")
33+
# An optional exclusive maximum version.
34+
max_version = os.environ.get("DOCKER_VERSION_MAX")
35+
with host.sudo("stack"):
36+
client_version = parse(host.docker.client_version())
37+
server_version = parse(host.docker.server_version())
38+
if min_version:
39+
min_version = parse(min_version)
40+
assert client_version >= min_version
41+
assert server_version >= min_version
42+
if max_version:
43+
max_version = parse(max_version)
44+
assert client_version < max_version
45+
assert server_version < max_version
46+
47+
48+
def test_docker_containers(subtests, host):
49+
"""Check that Docker containers are healthy."""
50+
with host.sudo("stack"):
51+
docker_containers = host.docker.get_containers()
52+
for container in docker_containers:
53+
# Use the subtests fixture to create a dynamically parametrised test
54+
# based on the containers on the system.
55+
with subtests.test(msg="container=" + container.name):
56+
state = container.inspect()["State"]
57+
assert state["Running"]
58+
assert not state["Restarting"]
59+
assert not state["Dead"]
60+
assert not state["OOMKilled"]
61+
if "Health" in state:
62+
assert state["Health"]["Status"] == "healthy"
63+
if "HostConfig" in state:
64+
assert state["HostConfig"]["LogConfig"]["Type"] == "json-file"
65+
assert "max-file" in state["HostConfig"]["LogConfig"]["Config"]
66+
assert "max-size" in state["HostConfig"]["LogConfig"]["Config"]
67+
68+
69+
def test_docker_driver(docker_info):
70+
"""Check that Docker is using the overlay2 storage driver."""
71+
assert docker_info["Driver"] == "overlay2"
72+
73+
74+
def test_no_bridge_network_exists(host):
75+
"""Check that no bridge network exists."""
76+
with host.sudo("stack"):
77+
docker_networks = host.check_output("docker network ls --format json")
78+
for network in docker_networks.splitlines():
79+
network = json.loads(network)
80+
assert network["Name"] != "bridge"
81+
assert network["Driver"] != "bridge"
82+
83+
84+
def test_ip_forwarding_disabled(docker_info):
85+
"""Check that IP forwarding is disabled."""
86+
assert not docker_info["IPv4Forwarding"]
87+
88+
89+
def test_iptables_disabled(docker_info):
90+
"""Check that IPTables manipulation is disabled."""
91+
assert not docker_info["BridgeNfIptables"]
92+
assert not docker_info["BridgeNfIp6tables"]
93+
94+
95+
def test_live_restore_enabled(docker_info):
96+
"""Check that live restore is enabled."""
97+
assert docker_info["LiveRestoreEnabled"]

0 commit comments

Comments
 (0)