Skip to content

Commit c99ba70

Browse files
committed
Test that HAProxy routes correctly to Synapse workers
1 parent bcbfb7f commit c99ba70

3 files changed

Lines changed: 93 additions & 2 deletions

File tree

charts/matrix-stack/ci/fragments/synapse-pytest-self-extras.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,16 @@ synapse:
2020
# A non-HTTP worker & a stream writer
2121
event-persister:
2222
enabled: true
23+
# initial-synchrotron & synchrotron have non-trivial routing behaviour
24+
initial-synchrotron:
25+
enabled: true
2326
# A standard HTTP worker
2427
sliding-sync:
2528
replicas: 2
2629
enabled: true
30+
# initial-synchrotron & synchrotron have non-trivial routing behaviour
31+
synchrotron:
32+
enabled: true
2733
# Media repo is fairly distinct from other workers
2834
media-repository:
2935
enabled: true

charts/matrix-stack/ci/pytest-synapse-values.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,18 @@ synapse:
5858
# A non-HTTP worker & a stream writer
5959
event-persister:
6060
enabled: true
61+
# initial-synchrotron & synchrotron have non-trivial routing behaviour
62+
initial-synchrotron:
63+
enabled: true
6164
# Media repo is fairly distinct from other workers
6265
media-repository:
6366
enabled: true
6467
# A standard HTTP worker
6568
sliding-sync:
6669
enabled: true
6770
replicas: 2
71+
# initial-synchrotron & synchrotron have non-trivial routing behaviour
72+
synchrotron:
73+
enabled: true
6874
wellKnownDelegation:
6975
enabled: false

tests/integration/test_synapse.py

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
import hashlib
66
from pathlib import Path
77

8+
import aiohttp
89
import pyhelm3
910
import pytest
11+
from aiohttp_retry import RetryClient
12+
from lightkube import AsyncClient
13+
from lightkube.resources.core_v1 import Pod
1014

1115
from .fixtures import ESSData, User
1216
from .lib.helpers import deploy_with_values_patch, get_deployment_marker
1317
from .lib.synapse import assert_downloaded_content, download_media, upload_media
14-
from .lib.utils import KubeCtl, aiohttp_client, aiohttp_get_json, aiohttp_post_json, value_file_has
18+
from .lib.utils import KubeCtl, aiohttp_client, aiohttp_get_json, aiohttp_post_json, retry_options, value_file_has
1519

1620

1721
@pytest.mark.skipif(value_file_has("synapse.enabled", False), reason="Synapse not deployed")
@@ -35,7 +39,9 @@ async def test_synapse_can_access_client_api(
3539
@pytest.mark.skipif(value_file_has("synapse.enabled", False), reason="Synapse not deployed")
3640
@pytest.mark.parametrize("users", [(User(name="sliding-sync-user"),)], indirect=True)
3741
@pytest.mark.asyncio_cooperative
38-
async def test_simplified_sliding_sync_syncs(ssl_context, users, generated_data: ESSData):
42+
async def test_simplified_sliding_sync_syncs(ingress_ready, ssl_context, users, generated_data: ESSData):
43+
await ingress_ready("synapse")
44+
3945
access_token = users[0].access_token
4046

4147
sync_result = await aiohttp_post_json(
@@ -48,6 +54,79 @@ async def test_simplified_sliding_sync_syncs(ssl_context, users, generated_data:
4854
assert "pos" in sync_result
4955

5056

57+
@pytest.mark.skipif(value_file_has("synapse.enabled", False), reason="Synapse not deployed")
58+
@pytest.mark.asyncio_cooperative
59+
async def test_routes_to_synapse_workers_correctly(
60+
ingress_ready, kube_client: AsyncClient, ssl_context, generated_data: ESSData
61+
):
62+
await ingress_ready("synapse")
63+
64+
main_backend = "main/main"
65+
if value_file_has("synapse.workers.sliding-sync.enabled", True):
66+
sliding_sync_backend = "sliding-sync/sliding-sync"
67+
else:
68+
sliding_sync_backend = main_backend
69+
70+
if value_file_has("synapse.workers.synchrotron.enabled", True):
71+
synchrotron_backend = "synchrotron/synchrotron"
72+
else:
73+
synchrotron_backend = main_backend
74+
75+
if value_file_has("synapse.workers.initial-synchrotron.enabled", True):
76+
initial_synchrotron_backend = "initial-synchrotron/initial-sync"
77+
else:
78+
initial_synchrotron_backend = synchrotron_backend
79+
80+
# We don't care about any of these succeeding, only that the requests are made and HAProxy dispatches correctly
81+
# So no auth required and parameters can be made up
82+
paths_to_backends = {
83+
# initial-synchrotron
84+
"/_matrix/client/v3/initialSync": initial_synchrotron_backend,
85+
"/_matrix/client/v3/rooms/aroomid/initialSync": initial_synchrotron_backend,
86+
"/_matrix/client/v3/sync?full_state=true": initial_synchrotron_backend,
87+
"/_matrix/client/v3/sync": initial_synchrotron_backend,
88+
"/_matrix/client/v3/events": initial_synchrotron_backend,
89+
# synchrotron
90+
"/_matrix/client/v3/sync?since=recently": synchrotron_backend,
91+
"/_matrix/client/v3/events?from=recently": synchrotron_backend,
92+
# sliding-sync
93+
"/_matrix/client/unstable/org.matrix.simplified_msc3575/sync": sliding_sync_backend,
94+
# Would be client-reader but not configured in tests
95+
"/_matrix/client/versions": main_backend,
96+
}
97+
98+
for path in paths_to_backends:
99+
host = f"synapse.{generated_data.server_name}"
100+
url = f"https://127.0.0.1{path}"
101+
async with (
102+
aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context)) as session,
103+
RetryClient(session, retry_options=retry_options, raise_for_status=False) as client,
104+
client.get(url, headers={"Host": host}, server_hostname=host) as response,
105+
):
106+
# 200 for no auth required (/_matrix/client/versions)
107+
# 401 for most paths that require auth
108+
# 405 for sliding sync that doesn't do GET
109+
assert response.status in [200, 401, 405], f"{path} had an unexpected status"
110+
111+
http_log_lines = []
112+
async for haproxy_pod in kube_client.list(
113+
Pod, namespace=generated_data.ess_namespace, labels={"app.kubernetes.io/name": "haproxy"}
114+
):
115+
assert haproxy_pod.metadata
116+
assert haproxy_pod.metadata.name
117+
assert haproxy_pod.metadata.namespace
118+
async for log_line in kube_client.log(haproxy_pod.metadata.name, namespace=haproxy_pod.metadata.namespace):
119+
if "HTTP/1.1" in log_line:
120+
http_log_lines.append(log_line)
121+
122+
for path, backend in paths_to_backends.items():
123+
matching_lines = [line for line in http_log_lines if f"GET {path} HTTP/1.1" in line]
124+
125+
assert len(matching_lines) > 0, f"Requests for {path} did not appear in the HAProxy logs"
126+
for matching_line in matching_lines:
127+
assert f"synapse-http-in synapse-{backend}" in matching_line, f"{path} was routed unexpectedly"
128+
129+
51130
@pytest.mark.skipif(value_file_has("synapse.enabled", False), reason="Synapse not deployed")
52131
@pytest.mark.parametrize("users", [(User(name="media-upload-unauth"),)], indirect=True)
53132
@pytest.mark.asyncio_cooperative

0 commit comments

Comments
 (0)