Skip to content

Commit 21fac34

Browse files
authored
New Example: examples/vhost (#248)
1 parent fb092cc commit 21fac34

File tree

8 files changed

+219
-0
lines changed

8 files changed

+219
-0
lines changed

.github/workflows/examples.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,36 @@ jobs:
266266
timeout-minutes: 10
267267
run: |
268268
pytest -xsv tests
269+
270+
vhost:
271+
runs-on: ${{ matrix.os }}
272+
273+
strategy:
274+
fail-fast: false
275+
matrix:
276+
python-version: ["3.12"]
277+
os: ["ubuntu-latest"]
278+
279+
steps:
280+
- name: Install apt packages
281+
if: startsWith(matrix.os, 'ubuntu-')
282+
run: |
283+
sudo apt update
284+
- uses: actions/checkout@v4
285+
- name: Set up Python ${{ matrix.python-version }}
286+
uses: actions/setup-python@v5
287+
with:
288+
python-version: ${{ matrix.python-version }}
289+
cache: 'pip'
290+
cache-dependency-path: '**/setup.py'
291+
- name: Install dependencies
292+
working-directory: examples/vhost
293+
run: |
294+
python -m pip install --upgrade pip
295+
pip install -r requirements.txt
296+
297+
- name: Run tests
298+
working-directory: examples/vhost
299+
timeout-minutes: 10
300+
run: |
301+
pytest -xsv tests

docs/userguide/examples/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ Every example is an independent project and is tested via the
2121
rabbitmq_management
2222
range
2323
myutils
24+
vhost
2425
django
2526
hybrid_setup

docs/userguide/examples/vhost.rst

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
.. _examples_vhost:
2+
3+
=======
4+
vhost
5+
=======
6+
7+
:Release: |version|
8+
:Date: |today|
9+
10+
.. contents::
11+
:local:
12+
:depth: 2
13+
14+
Description
15+
===========
16+
17+
This example project demonstrates how to use a single Redis container as both a broker and a result backend,
18+
using different vhosts for each purpose.
19+
20+
Breakdown
21+
=========
22+
23+
File Structure
24+
~~~~~~~~~~~~~~
25+
26+
The following diagram lists the relevant files in the project.
27+
28+
.. code-block:: text
29+
30+
rabbitmq_management/
31+
├── tests/
32+
│ ├── __init__.py
33+
│ ├── conftest.py
34+
│ └── test_vhost.py
35+
└── requirements.txt
36+
37+
conftest.py
38+
~~~~~~~~~~~
39+
40+
We create our own Redis container, and then use it as both a broker and a result backend.
41+
42+
.. code-block:: python
43+
44+
redis_image = fetch(repository=REDIS_IMAGE)
45+
redis_test_container: RedisContainer = container(
46+
image="{redis_image.id}",
47+
ports=REDIS_PORTS,
48+
environment=REDIS_ENV,
49+
network="{default_pytest_celery_network.name}",
50+
wrapper_class=RedisContainer,
51+
timeout=REDIS_CONTAINER_TIMEOUT,
52+
)
53+
54+
As the default vhost is "0", we can use it as the broker, and create a new vhost for the result backend.
55+
56+
.. code-block:: python
57+
58+
@pytest.fixture
59+
def redis_broker(redis_test_container: RedisContainer) -> RedisTestBroker:
60+
broker = RedisTestBroker(redis_test_container)
61+
yield broker
62+
broker.teardown()
63+
64+
65+
@pytest.fixture
66+
def celery_broker_cluster(redis_broker: RedisTestBroker) -> CeleryBrokerCluster:
67+
cluster = CeleryBrokerCluster(redis_broker)
68+
yield cluster
69+
cluster.teardown()
70+
71+
For the backend, we need to change some settings to use a different vhost, so we create our own
72+
Redis backend and work it out there.
73+
74+
.. code-block:: python
75+
76+
class MyRedisTestBackend(RedisTestBackend):
77+
def config(self, *args: tuple, **kwargs: dict) -> dict:
78+
return super().config(vhost=1, *args, **kwargs)
79+
80+
Lastly, we add our backend that uses the same Redis container as the broker and our
81+
``MyRedisTestBackend`` class.
82+
83+
.. code-block:: python
84+
85+
@pytest.fixture
86+
def redis_backend(redis_test_container: RedisContainer) -> MyRedisTestBackend:
87+
backend = MyRedisTestBackend(redis_test_container)
88+
yield backend
89+
backend.teardown()
90+
91+
92+
@pytest.fixture
93+
def celery_backend_cluster(redis_backend: MyRedisTestBackend) -> CeleryBackendCluster:
94+
cluster = CeleryBackendCluster(redis_backend)
95+
yield cluster
96+
cluster.teardown()
97+
98+
test_vhost.py
99+
~~~~~~~~~~~~~
100+
101+
We can now run tests that will share the same Redis container for both the broker and the result backend components.
102+
103+
.. literalinclude:: ../../../examples/vhost/tests/test_vhost.py
104+
:language: python
105+
:caption: examples.vhost.tests.test_vhost.py

examples/vhost/pytest.ini

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[pytest]
2+
log_cli = true
3+
log_cli_level = INFO
4+
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
5+
log_cli_date_format = %Y-%m-%d %H:%M:%S

examples/vhost/requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pytest>=7.4.4
2+
pytest-xdist>=3.5.0
3+
pytest-celery[all]@git+https://github.com/celery/pytest-celery.git

examples/vhost/tests/__init__.py

Whitespace-only changes.

examples/vhost/tests/conftest.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import pytest
2+
from pytest_docker_tools import container
3+
from pytest_docker_tools import fetch
4+
5+
from pytest_celery import REDIS_CONTAINER_TIMEOUT
6+
from pytest_celery import REDIS_ENV
7+
from pytest_celery import REDIS_IMAGE
8+
from pytest_celery import REDIS_PORTS
9+
from pytest_celery import CeleryBackendCluster
10+
from pytest_celery import CeleryBrokerCluster
11+
from pytest_celery import RedisContainer
12+
from pytest_celery import RedisTestBackend
13+
from pytest_celery import RedisTestBroker
14+
15+
redis_image = fetch(repository=REDIS_IMAGE)
16+
redis_test_container: RedisContainer = container(
17+
image="{redis_image.id}",
18+
ports=REDIS_PORTS,
19+
environment=REDIS_ENV,
20+
network="{default_pytest_celery_network.name}",
21+
wrapper_class=RedisContainer,
22+
timeout=REDIS_CONTAINER_TIMEOUT,
23+
)
24+
25+
26+
@pytest.fixture
27+
def redis_broker(redis_test_container: RedisContainer) -> RedisTestBroker:
28+
broker = RedisTestBroker(redis_test_container)
29+
yield broker
30+
broker.teardown()
31+
32+
33+
@pytest.fixture
34+
def celery_broker_cluster(redis_broker: RedisTestBroker) -> CeleryBrokerCluster:
35+
cluster = CeleryBrokerCluster(redis_broker)
36+
yield cluster
37+
cluster.teardown()
38+
39+
40+
class MyRedisTestBackend(RedisTestBackend):
41+
def config(self, *args: tuple, **kwargs: dict) -> dict:
42+
return super().config(vhost=1, *args, **kwargs)
43+
44+
45+
@pytest.fixture
46+
def redis_backend(redis_test_container: RedisContainer) -> MyRedisTestBackend:
47+
backend = MyRedisTestBackend(redis_test_container)
48+
yield backend
49+
backend.teardown()
50+
51+
52+
@pytest.fixture
53+
def celery_backend_cluster(redis_backend: MyRedisTestBackend) -> CeleryBackendCluster:
54+
cluster = CeleryBackendCluster(redis_backend)
55+
yield cluster
56+
cluster.teardown()

examples/vhost/tests/test_vhost.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from pytest_celery import RESULT_TIMEOUT
2+
from pytest_celery import CeleryTestSetup
3+
from pytest_celery import ping
4+
5+
6+
class TestVhost:
7+
def test_ping(self, celery_setup: CeleryTestSetup):
8+
assert ping.s().delay().get(timeout=RESULT_TIMEOUT) == "pong"
9+
10+
def test_vhost(self, celery_setup: CeleryTestSetup):
11+
assert celery_setup.app.conf.broker_url[:-1] == celery_setup.app.conf.result_backend[:-1]
12+
assert celery_setup.app.conf.broker_url.endswith("/0")
13+
assert celery_setup.app.conf.result_backend.endswith("/1")
14+
15+
def test_single_redis(self, celery_setup: CeleryTestSetup):
16+
assert celery_setup.broker.container.id == celery_setup.backend.container.id

0 commit comments

Comments
 (0)