Skip to content

Commit faf1dda

Browse files
Fix integration tests
1 parent a03211f commit faf1dda

File tree

4 files changed

+54
-144
lines changed

4 files changed

+54
-144
lines changed

poetry.lock

Lines changed: 14 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ package-mode = false
66
requires-poetry = ">=2.0.0"
77

88
[tool.poetry.dependencies]
9-
python = "^3.8.6" # ^3.8.6 required by juju
9+
python = "^3.9.0" # ^3.9.0 required by tomli-w
1010
# breaking change in ops 2.10.0: https://github.com/canonical/operator/pull/1091#issuecomment-1888644075
1111
ops = "^2.9.0, <2.10"
1212
tenacity = "^9.0.0"
@@ -55,6 +55,8 @@ mysql-connector-python = "~8.0.33"
5555
tenacity = "^9.0.0"
5656
ops = "^2.9.0"
5757
allure-pytest-default-results = "^0.1.2"
58+
tomli = "^2.2.1"
59+
tomli-w = "^1.2.0"
5860

5961
[tool.poetry.group.build-refresh-version]
6062
optional = true

tests/integration/helpers.py

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from typing import Dict, List, Optional
99

1010
import tenacity
11-
from juju.model import Model
1211
from juju.unit import Unit
1312
from pytest_operator.plugin import OpsTest
1413

@@ -410,41 +409,6 @@ async def ensure_all_units_continuous_writes_incrementing(
410409
last_max_written_value = max_written_value
411410

412411

413-
async def get_workload_version(ops_test: OpsTest, unit_name: str) -> str:
414-
"""Get the workload version of the deployed router charm."""
415-
return_code, output, _ = await ops_test.juju(
416-
"ssh",
417-
unit_name,
418-
"sudo",
419-
"cat",
420-
f"/var/lib/juju/agents/unit-{unit_name.replace('/', '-')}/charm/workload_version",
421-
)
422-
423-
assert return_code == 0
424-
return output.strip()
425-
426-
427-
async def get_leader_unit(
428-
ops_test: Optional[OpsTest], app_name: str, model: Optional[Model] = None
429-
) -> Optional[Unit]:
430-
"""Get the leader unit of a given application.
431-
432-
Args:
433-
ops_test: The ops test framework instance
434-
app_name: The name of the application
435-
model: The model to use (overrides ops_test.model)
436-
"""
437-
leader_unit = None
438-
if not model:
439-
model = ops_test.model
440-
for unit in model.applications[app_name].units:
441-
if await unit.is_leader_from_status():
442-
leader_unit = unit
443-
break
444-
445-
return leader_unit
446-
447-
448412
def get_juju_status(model_name: str) -> str:
449413
"""Return the juju status output.
450414

tests/integration/test_upgrade.py

Lines changed: 37 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,21 @@
55
import logging
66
import os
77
import pathlib
8-
import platform
9-
import re
108
import shutil
119
import typing
1210
import zipfile
1311

1412
import pytest
15-
import tenacity
13+
import tomli
14+
import tomli_w
15+
from packaging.version import Version
1616
from pytest_operator.plugin import OpsTest
1717

18-
import snap
19-
2018
from .helpers import (
2119
APPLICATION_DEFAULT_APP_NAME,
2220
MYSQL_DEFAULT_APP_NAME,
2321
MYSQL_ROUTER_DEFAULT_APP_NAME,
2422
ensure_all_units_continuous_writes_incrementing,
25-
get_juju_status,
26-
get_leader_unit,
27-
get_workload_version,
2823
)
2924
from .juju_ import run_action
3025

@@ -87,9 +82,6 @@ async def test_upgrade_from_edge(ops_test: OpsTest, charm, continuous_writes) ->
8782
await ensure_all_units_continuous_writes_incrementing(ops_test)
8883

8984
mysql_router_application = ops_test.model.applications[MYSQL_ROUTER_APP_NAME]
90-
mysql_router_unit = mysql_router_application.units[0]
91-
92-
old_workload_version = await get_workload_version(ops_test, mysql_router_unit.name)
9385

9486
logger.info("Build charm locally")
9587
global temporary_charm
@@ -107,23 +99,26 @@ async def test_upgrade_from_edge(ops_test: OpsTest, charm, continuous_writes) ->
10799
lambda: mysql_router_application.status == "blocked", timeout=TIMEOUT
108100
)
109101
assert (
110-
"resume-upgrade" in mysql_router_application.status_message
111-
), "mysql router application status not indicating that user should resume upgrade"
112-
113-
for attempt in tenacity.Retrying(
114-
reraise=True,
115-
stop=tenacity.stop_after_delay(SMALL_TIMEOUT),
116-
wait=tenacity.wait_fixed(10),
117-
):
118-
with attempt:
119-
assert "+testupgrade" in get_juju_status(
120-
ops_test.model.name
121-
), "None of the units are upgraded"
102+
"resume-refresh" in mysql_router_application.status_message
103+
), "mysql router application status not indicating that user should resume refresh"
104+
105+
logger.info("Wait for first unit to upgrade")
106+
async with ops_test.fast_forward("60s"):
107+
await ops_test.model.wait_for_idle(
108+
[MYSQL_ROUTER_APP_NAME],
109+
idle_period=30,
110+
timeout=TIMEOUT,
111+
)
122112

123-
mysql_router_leader_unit = await get_leader_unit(ops_test, MYSQL_ROUTER_APP_NAME)
113+
# Highest to lowest unit number
114+
refresh_order = sorted(
115+
mysql_router_application.units,
116+
key=lambda unit: int(unit.name.split("/")[1]),
117+
reverse=True,
118+
)
124119

125-
logger.info("Running resume-upgrade on the mysql router leader unit")
126-
await run_action(mysql_router_leader_unit, "resume-upgrade")
120+
logger.info("Running resume-refresh on the mysql router leader unit")
121+
await run_action(refresh_order[1], "resume-refresh")
127122

128123
logger.info("Waiting for upgrade to complete on all units")
129124
await ops_test.model.wait_for_idle(
@@ -133,14 +128,6 @@ async def test_upgrade_from_edge(ops_test: OpsTest, charm, continuous_writes) ->
133128
timeout=UPGRADE_TIMEOUT,
134129
)
135130

136-
workload_version_file = pathlib.Path("workload_version")
137-
repo_workload_version = workload_version_file.read_text().strip()
138-
139-
for unit in mysql_router_application.units:
140-
workload_version = await get_workload_version(ops_test, unit.name)
141-
assert workload_version == f"{repo_workload_version}+testupgrade"
142-
assert old_workload_version != workload_version
143-
144131
await ensure_all_units_continuous_writes_incrementing(ops_test)
145132

146133
await ops_test.model.wait_for_idle(
@@ -189,17 +176,6 @@ async def test_fail_and_rollback(ops_test: OpsTest, charm, continuous_writes) ->
189176
apps=[MYSQL_ROUTER_APP_NAME], status="active", timeout=TIMEOUT, idle_period=30
190177
)
191178

192-
workload_version_file = pathlib.Path("workload_version")
193-
repo_workload_version = workload_version_file.read_text().strip()
194-
195-
for unit in mysql_router_application.units:
196-
charm_workload_version = await get_workload_version(ops_test, unit.name)
197-
assert charm_workload_version == f"{repo_workload_version}+testupgrade"
198-
199-
await ops_test.model.wait_for_idle(
200-
apps=[MYSQL_ROUTER_APP_NAME], status="active", timeout=TIMEOUT
201-
)
202-
203179
logger.info("Ensure continuous writes after rollback procedure")
204180
await ensure_all_units_continuous_writes_incrementing(ops_test)
205181

@@ -212,31 +188,28 @@ def create_valid_upgrade_charm(charm_file: typing.Union[str, pathlib.Path]) -> N
212188
213189
Upgrades require a new snap revision to avoid no-oping.
214190
"""
215-
workload_version_file = pathlib.Path("workload_version")
216-
workload_version = workload_version_file.read_text().strip()
191+
with pathlib.Path("refresh_versions.toml").open("rb") as file:
192+
versions = tomli.load(file)
193+
194+
# charm needs to refresh snap to be able to avoid no-op when upgrading.
195+
# set an old revision of the snap
196+
versions["snap"]["revisions"]["x86_64"] = "121"
197+
versions["snap"]["revisions"]["aarch64"] = "122"
217198

218199
with zipfile.ZipFile(charm_file, mode="a") as charm_zip:
219-
charm_zip.writestr("workload_version", f"{workload_version}+testupgrade\n")
220-
221-
# charm needs to refresh snap to be able to avoid no-op when upgrading.
222-
# set an old revision of the snap
223-
snap_file = pathlib.Path("src/snap.py")
224-
content = snap_file.read_text()
225-
old_revision = {"x86_64": "121", "aarch64": "122"}[platform.machine()]
226-
new_snap_content = re.sub(
227-
f'"{platform.machine()}": "{snap.revision}"',
228-
f'"{platform.machine()}": "{old_revision}"',
229-
str(content),
230-
)
231-
charm_zip.writestr("src/snap.py", new_snap_content)
200+
charm_zip.writestr("refresh_versions.toml", tomli_w.dumps(versions))
232201

233202

234203
def create_invalid_upgrade_charm(charm_file: typing.Union[str, pathlib.Path]) -> None:
235204
"""Create an invalid mysql router charm for upgrade."""
236-
workload_version_file = pathlib.Path("workload_version")
237-
old_workload_version = workload_version_file.read_text().strip()
238-
[major, minor, patch] = old_workload_version.split(".")
205+
with pathlib.Path("refresh_versions.toml").open("rb") as file:
206+
versions = tomli.load(file)
207+
208+
old_version = Version(versions["workload"])
209+
new_version = Version(f"{old_version.major - 1}.{old_version.minor}.{old_version.micro}")
210+
versions["workload"] = str(new_version)
211+
versions["charm"] = "8.0/0.0.0"
239212

240213
with zipfile.ZipFile(charm_file, mode="a") as charm_zip:
241214
# an invalid charm version because the major workload_version is one less than the current workload_version
242-
charm_zip.writestr("workload_version", f"{int(major) - 1}.{minor}.{patch}+testrollback\n")
215+
charm_zip.writestr("refresh_versions.toml", tomli_w.dumps(versions))

0 commit comments

Comments
 (0)