Skip to content

Commit a0d3948

Browse files
authored
DPE-4613 Test for multi-relation scale in/out (#489)
* test for multiple relations being scaled in/out together * fallback for juju 2.x tests * increased scale * use different dbs * fix block until to account for units count * avoid pod label update for every relation * bigger timeouts required
1 parent 9a20ea8 commit a0d3948

File tree

2 files changed

+105
-4
lines changed

2 files changed

+105
-4
lines changed

src/relations/mysql_provider.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,13 @@ def _configure_endpoints(self, _) -> None:
222222

223223
relation_data = self.database.fetch_relation_data()
224224
for relation in relations:
225-
# only update endpoints if on_database_requested has executed
226-
if relation.id not in relation_data:
227-
continue
225+
# only update endpoints if on_database_requested on any
226+
# relation
227+
if relation.id in relation_data:
228+
break
229+
return
228230

229-
self.charm._mysql.update_endpoints()
231+
self.charm._mysql.update_endpoints()
230232

231233
def _on_update_status(self, _) -> None:
232234
"""Handle the update status event.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/usr/bin/env python3
2+
# Copyright 2024 Canonical Ltd.
3+
# See LICENSE file for licensing details.
4+
5+
6+
from pathlib import Path
7+
8+
import pytest
9+
import yaml
10+
from pytest_operator.plugin import OpsTest
11+
12+
DB_METADATA = yaml.safe_load(Path("./metadata.yaml").read_text())
13+
SCALE_APPS = 7
14+
SCALE_UNITS = 3
15+
16+
17+
@pytest.mark.group(1)
18+
@pytest.mark.abort_on_fail
19+
async def test_build_and_deploy(ops_test: OpsTest):
20+
"""Build the charm and deploy 1 units to ensure a cluster is formed."""
21+
# Build and deploy charm from local source folder
22+
db_charm = await ops_test.build_charm(".")
23+
24+
config = {"profile": "testing"}
25+
resources = {"mysql-image": DB_METADATA["resources"]["mysql-image"]["upstream-source"]}
26+
27+
await ops_test.model.deploy(
28+
db_charm,
29+
application_name="mysql",
30+
config=config,
31+
num_units=1,
32+
resources=resources,
33+
series="jammy",
34+
trust=True,
35+
)
36+
37+
for i in range(SCALE_APPS):
38+
config = {"database_name": f"database{i}", "sleep_interval": "2000"}
39+
await ops_test.model.deploy(
40+
"mysql-test-app",
41+
application_name=f"app{i}",
42+
num_units=1,
43+
channel="latest/edge",
44+
config=config,
45+
)
46+
await ops_test.model.deploy(
47+
"mysql-router-k8s",
48+
application_name=f"router{i}",
49+
num_units=1,
50+
channel="8.0/edge",
51+
trust=True,
52+
)
53+
54+
55+
@pytest.mark.group(1)
56+
@pytest.mark.abort_on_fail
57+
async def test_relate_all(ops_test: OpsTest):
58+
"""Relate all the applications to the database."""
59+
for i in range(SCALE_APPS):
60+
await ops_test.model.relate("mysql:database", f"router{i}:backend-database")
61+
await ops_test.model.relate(f"app{i}:database", f"router{i}:database")
62+
63+
await ops_test.model.block_until(
64+
lambda: all(unit.workload_status == "active" for unit in ops_test.model.units.values()),
65+
timeout=60 * 25,
66+
wait_period=5,
67+
)
68+
69+
70+
@pytest.mark.group(1)
71+
@pytest.mark.abort_on_fail
72+
async def test_scale_out(ops_test: OpsTest):
73+
"""Scale database and routers."""
74+
await ops_test.model.applications["mysql"].scale(SCALE_UNITS)
75+
for i in range(SCALE_APPS):
76+
await ops_test.model.applications[f"router{i}"].scale(SCALE_UNITS)
77+
expected_unit_sum = SCALE_UNITS + 4 * SCALE_APPS
78+
await ops_test.model.block_until(
79+
lambda: all(unit.workload_status == "active" for unit in ops_test.model.units.values())
80+
and len(ops_test.model.units) == expected_unit_sum,
81+
timeout=60 * 30,
82+
wait_period=5,
83+
)
84+
85+
86+
@pytest.mark.group(1)
87+
@pytest.mark.abort_on_fail
88+
async def test_scale_in(ops_test: OpsTest):
89+
"""Scale database and routers."""
90+
await ops_test.model.applications["mysql"].scale(1)
91+
for i in range(SCALE_APPS):
92+
await ops_test.model.applications[f"router{i}"].scale(1)
93+
expected_unit_sum = 1 + 2 * SCALE_APPS
94+
await ops_test.model.block_until(
95+
lambda: all(unit.workload_status == "active" for unit in ops_test.model.units.values())
96+
and len(ops_test.model.units) == expected_unit_sum,
97+
timeout=60 * 15,
98+
wait_period=5,
99+
)

0 commit comments

Comments
 (0)