5
5
import logging
6
6
import os
7
7
import pathlib
8
- import platform
9
- import re
10
8
import shutil
11
9
import typing
12
10
import zipfile
13
11
14
12
import pytest
15
- import tenacity
13
+ import tomli
14
+ import tomli_w
15
+ from packaging .version import Version
16
16
from pytest_operator .plugin import OpsTest
17
17
18
- import snap
19
-
20
18
from .helpers import (
21
19
APPLICATION_DEFAULT_APP_NAME ,
22
20
MYSQL_DEFAULT_APP_NAME ,
23
21
MYSQL_ROUTER_DEFAULT_APP_NAME ,
24
22
ensure_all_units_continuous_writes_incrementing ,
25
- get_juju_status ,
26
- get_leader_unit ,
27
- get_workload_version ,
28
23
)
29
24
from .juju_ import run_action
30
25
@@ -91,9 +86,6 @@ async def test_upgrade_from_edge(ops_test: OpsTest, charm, continuous_writes) ->
91
86
await ensure_all_units_continuous_writes_incrementing (ops_test )
92
87
93
88
mysql_router_application = ops_test .model .applications [MYSQL_ROUTER_APP_NAME ]
94
- mysql_router_unit = mysql_router_application .units [0 ]
95
-
96
- old_workload_version = await get_workload_version (ops_test , mysql_router_unit .name )
97
89
98
90
logger .info ("Build charm locally" )
99
91
global temporary_charm
@@ -111,23 +103,26 @@ async def test_upgrade_from_edge(ops_test: OpsTest, charm, continuous_writes) ->
111
103
lambda : mysql_router_application .status == "blocked" , timeout = TIMEOUT
112
104
)
113
105
assert (
114
- "resume-upgrade" in mysql_router_application .status_message
115
- ), "mysql router application status not indicating that user should resume upgrade"
116
-
117
- for attempt in tenacity .Retrying (
118
- reraise = True ,
119
- stop = tenacity .stop_after_delay (SMALL_TIMEOUT ),
120
- wait = tenacity .wait_fixed (10 ),
121
- ):
122
- with attempt :
123
- assert "+testupgrade" in get_juju_status (
124
- ops_test .model .name
125
- ), "None of the units are upgraded"
106
+ "resume-refresh" in mysql_router_application .status_message
107
+ ), "mysql router application status not indicating that user should resume refresh"
108
+
109
+ logger .info ("Wait for first unit to upgrade" )
110
+ async with ops_test .fast_forward ("60s" ):
111
+ await ops_test .model .wait_for_idle (
112
+ [MYSQL_ROUTER_APP_NAME ],
113
+ idle_period = 30 ,
114
+ timeout = TIMEOUT ,
115
+ )
126
116
127
- mysql_router_leader_unit = await get_leader_unit (ops_test , MYSQL_ROUTER_APP_NAME )
117
+ # Highest to lowest unit number
118
+ refresh_order = sorted (
119
+ mysql_router_application .units ,
120
+ key = lambda unit : int (unit .name .split ("/" )[1 ]),
121
+ reverse = True ,
122
+ )
128
123
129
- logger .info ("Running resume-upgrade on the mysql router leader unit" )
130
- await run_action (mysql_router_leader_unit , "resume-upgrade " )
124
+ logger .info ("Running resume-refresh on the mysql router leader unit" )
125
+ await run_action (refresh_order [ 1 ] , "resume-refresh " )
131
126
132
127
logger .info ("Waiting for upgrade to complete on all units" )
133
128
await ops_test .model .wait_for_idle (
@@ -137,14 +132,6 @@ async def test_upgrade_from_edge(ops_test: OpsTest, charm, continuous_writes) ->
137
132
timeout = UPGRADE_TIMEOUT ,
138
133
)
139
134
140
- workload_version_file = pathlib .Path ("workload_version" )
141
- repo_workload_version = workload_version_file .read_text ().strip ()
142
-
143
- for unit in mysql_router_application .units :
144
- workload_version = await get_workload_version (ops_test , unit .name )
145
- assert workload_version == f"{ repo_workload_version } +testupgrade"
146
- assert old_workload_version != workload_version
147
-
148
135
await ensure_all_units_continuous_writes_incrementing (ops_test )
149
136
150
137
await ops_test .model .wait_for_idle (
@@ -193,17 +180,6 @@ async def test_fail_and_rollback(ops_test: OpsTest, charm, continuous_writes) ->
193
180
apps = [MYSQL_ROUTER_APP_NAME ], status = "active" , timeout = TIMEOUT , idle_period = 30
194
181
)
195
182
196
- workload_version_file = pathlib .Path ("workload_version" )
197
- repo_workload_version = workload_version_file .read_text ().strip ()
198
-
199
- for unit in mysql_router_application .units :
200
- charm_workload_version = await get_workload_version (ops_test , unit .name )
201
- assert charm_workload_version == f"{ repo_workload_version } +testupgrade"
202
-
203
- await ops_test .model .wait_for_idle (
204
- apps = [MYSQL_ROUTER_APP_NAME ], status = "active" , timeout = TIMEOUT
205
- )
206
-
207
183
logger .info ("Ensure continuous writes after rollback procedure" )
208
184
await ensure_all_units_continuous_writes_incrementing (ops_test )
209
185
@@ -216,31 +192,28 @@ def create_valid_upgrade_charm(charm_file: typing.Union[str, pathlib.Path]) -> N
216
192
217
193
Upgrades require a new snap revision to avoid no-oping.
218
194
"""
219
- workload_version_file = pathlib .Path ("workload_version" )
220
- workload_version = workload_version_file .read_text ().strip ()
195
+ with pathlib .Path ("refresh_versions.toml" ).open ("rb" ) as file :
196
+ versions = tomli .load (file )
197
+
198
+ # charm needs to refresh snap to be able to avoid no-op when upgrading.
199
+ # set an old revision of the snap
200
+ versions ["snap" ]["revisions" ]["x86_64" ] = "121"
201
+ versions ["snap" ]["revisions" ]["aarch64" ] = "122"
221
202
222
203
with zipfile .ZipFile (charm_file , mode = "a" ) as charm_zip :
223
- charm_zip .writestr ("workload_version" , f"{ workload_version } +testupgrade\n " )
224
-
225
- # charm needs to refresh snap to be able to avoid no-op when upgrading.
226
- # set an old revision of the snap
227
- snap_file = pathlib .Path ("src/snap.py" )
228
- content = snap_file .read_text ()
229
- old_revision = {"x86_64" : "121" , "aarch64" : "122" }[platform .machine ()]
230
- new_snap_content = re .sub (
231
- f'"{ platform .machine ()} ": "{ snap .revision } "' ,
232
- f'"{ platform .machine ()} ": "{ old_revision } "' ,
233
- str (content ),
234
- )
235
- charm_zip .writestr ("src/snap.py" , new_snap_content )
204
+ charm_zip .writestr ("refresh_versions.toml" , tomli_w .dumps (versions ))
236
205
237
206
238
207
def create_invalid_upgrade_charm (charm_file : typing .Union [str , pathlib .Path ]) -> None :
239
208
"""Create an invalid mysql router charm for upgrade."""
240
- workload_version_file = pathlib .Path ("workload_version" )
241
- old_workload_version = workload_version_file .read_text ().strip ()
242
- [major , minor , patch ] = old_workload_version .split ("." )
209
+ with pathlib .Path ("refresh_versions.toml" ).open ("rb" ) as file :
210
+ versions = tomli .load (file )
211
+
212
+ old_version = Version (versions ["workload" ])
213
+ new_version = Version (f"{ old_version .major - 1 } .{ old_version .minor } .{ old_version .micro } " )
214
+ versions ["workload" ] = str (new_version )
215
+ versions ["charm" ] = "8.0/0.0.0"
243
216
244
217
with zipfile .ZipFile (charm_file , mode = "a" ) as charm_zip :
245
218
# an invalid charm version because the major workload_version is one less than the current workload_version
246
- charm_zip .writestr ("workload_version " , f" { int ( major ) - 1 } . { minor } . { patch } +testrollback \n " )
219
+ charm_zip .writestr ("refresh_versions.toml " , tomli_w . dumps ( versions ) )
0 commit comments