Skip to content

Commit 0ce05ea

Browse files
juledwardepatl
andauthored
Add Podman as a container runtime option
Fixes Issue 15. Co-authored-by: Denis Patlazhan <[email protected]> Co-authored-by: Julian Edwards <[email protected]>
1 parent 7418cc9 commit 0ce05ea

File tree

4 files changed

+117
-22
lines changed

4 files changed

+117
-22
lines changed

.github/workflows/tests.yml

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,29 @@
1-
name: Run tests
1+
name: Run parallel tests
22

3-
on: ["push", "pull_request"]
3+
on: [push, pull_request]
44

55
jobs:
6-
76
test:
8-
7+
name: Tests / Python ${{ matrix.python-version }}
98
runs-on: ubuntu-latest
109
strategy:
1110
matrix:
12-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
11+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
1312

1413
steps:
15-
- uses: actions/checkout@v3
16-
17-
- name: Set up Python ${{ matrix.python-version }}
18-
uses: actions/setup-python@v3
19-
with:
20-
python-version: ${{ matrix.python-version }}
21-
22-
- name: Install dependencies
23-
run: |
24-
python -m pip install --upgrade pip
25-
pip install hatch
26-
27-
- name: Run tests
28-
run: |
29-
hatch run ci
30-
14+
- uses: actions/checkout@v3
15+
- name: Set up Python
16+
uses: actions/setup-python@v3
17+
with:
18+
python-version: ${{ matrix.python-version }}
19+
- name: Install dependencies
20+
run: |
21+
sudo apt-get update && sudo apt-get -y install podman
22+
podman --version
23+
systemctl --user enable podman
24+
systemctl --user start podman
25+
python -m pip install --upgrade pip
26+
pip install hatch
27+
- name: Run tests
28+
run: |
29+
hatch run ci

README.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ PG containers. You will need to do up to two extra things:
9292
can set the DBTESTTOOLS_PG_IP_ADDR environment variable.
9393

9494

95+
If you want to use Podman instead of Docker engine you will need to follow
96+
these steps:
97+
98+
1. Enable and start podman on your host
99+
```bash
100+
systemctl --user enable podman
101+
systemctl --user start podman
102+
```
103+
2. `export DBTESTTOOLS_USE_PODMAN=1` variable.
104+
95105
This code has been in use daily on a large project at Cisco for a few years
96106
now, and is very stable.
97107

dbtesttools/engines/postgres.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,26 @@ def has_savepoint(self):
9090
def setUp(self):
9191
"""Do all the work to bring up a working Postgres fixture."""
9292
super().setUp()
93+
# Podman integration: optionally override Docker socket
94+
if os.getenv("DBTESTTOOLS_USE_PODMAN") == "1":
95+
if sys.platform == "darwin":
96+
# MacOS Podman socket
97+
podman_socket = (
98+
f"unix://{os.getenv('HOME')}"
99+
f"/.local/share/containers/podman/machine/podman.sock"
100+
)
101+
else:
102+
# Linux Podman socket
103+
podman_socket = (
104+
f"unix:///run/user/{os.getuid()}/podman/podman.sock"
105+
)
106+
if os.path.exists(podman_socket.replace("unix://", "")):
107+
os.environ["DOCKER_HOST"] = podman_socket
108+
else:
109+
raise FileNotFoundError(
110+
f"Podman socket not found at {podman_socket}"
111+
)
112+
93113
self.client = docker.from_env()
94114
self.pull_image()
95115
self.find_free_port()
@@ -156,7 +176,7 @@ def set_up_test_database(self):
156176
cur.close()
157177
c.close()
158178

159-
@retry(psycopg2.OperationalError, tries=30, delay=1)
179+
@retry(psycopg2.OperationalError, tries=60, delay=1)
160180
def wait_for_pg_start(self):
161181
c = psycopg2.connect(
162182
"user='postgres' host='{ip}' port='{port}'"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import os
2+
import unittest
3+
import warnings
4+
5+
import testscenarios
6+
import testtools
7+
from sqlalchemy import text
8+
9+
from dbtesttools.engines.postgres import PostgresContainerFixture
10+
11+
warnings.filterwarnings("ignore", category=UserWarning, module="urllib3")
12+
13+
14+
class TestPostgresContainer(
15+
testscenarios.TestWithScenarios, testtools.TestCase
16+
):
17+
"""Test that we can bring up a Postgres container."""
18+
19+
scenarios = [
20+
("docker", {"podman": False}),
21+
("podman", {"podman": True}),
22+
]
23+
24+
def setUp(self):
25+
self.pg_fixture = None
26+
super().setUp()
27+
if self.podman:
28+
os.environ["DBTESTTOOLS_USE_PODMAN"] = "1"
29+
else:
30+
os.environ.pop("DBTESTTOOLS_USE_PODMAN", None)
31+
try:
32+
fixture = PostgresContainerFixture(future=True)
33+
fixture.setUp()
34+
self.pg_fixture = fixture
35+
except Exception as e:
36+
print(f'[ERROR] Failed to start Postgres fixture: {e}')
37+
38+
def tearDown(self):
39+
if self.pg_fixture is not None:
40+
if hasattr(self.pg_fixture, "engine"):
41+
try:
42+
self.pg_fixture.engine.dispose()
43+
except Exception as e:
44+
print(f"Warning: failed to dispose engine: {e}")
45+
if hasattr(self.pg_fixture, "container"):
46+
try:
47+
self.pg_fixture.container.kill()
48+
except Exception as e:
49+
print(f"Warning: failed to kill container: {e}")
50+
super().tearDown()
51+
52+
def test_connection(self):
53+
if self.pg_fixture is None:
54+
self.fail("Postgres fixture was not initialized")
55+
# Actually test that the database is reachable
56+
conn = self.pg_fixture.connect()
57+
try:
58+
result = conn.execute(text("SELECT 1;"))
59+
value = result.scalar()
60+
self.assertEqual(value, 1)
61+
finally:
62+
conn.close()
63+
64+
65+
if __name__ == "__main__":
66+
unittest.main()

0 commit comments

Comments
 (0)