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
@@ -87,9 +82,6 @@ async def test_upgrade_from_edge(ops_test: OpsTest, charm, continuous_writes) ->
87
82
await ensure_all_units_continuous_writes_incrementing (ops_test )
88
83
89
84
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 )
93
85
94
86
logger .info ("Build charm locally" )
95
87
global temporary_charm
@@ -107,23 +99,26 @@ async def test_upgrade_from_edge(ops_test: OpsTest, charm, continuous_writes) ->
107
99
lambda : mysql_router_application .status == "blocked" , timeout = TIMEOUT
108
100
)
109
101
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
+ )
122
112
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
+ )
124
119
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 " )
127
122
128
123
logger .info ("Waiting for upgrade to complete on all units" )
129
124
await ops_test .model .wait_for_idle (
@@ -133,14 +128,6 @@ async def test_upgrade_from_edge(ops_test: OpsTest, charm, continuous_writes) ->
133
128
timeout = UPGRADE_TIMEOUT ,
134
129
)
135
130
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
-
144
131
await ensure_all_units_continuous_writes_incrementing (ops_test )
145
132
146
133
await ops_test .model .wait_for_idle (
@@ -189,17 +176,6 @@ async def test_fail_and_rollback(ops_test: OpsTest, charm, continuous_writes) ->
189
176
apps = [MYSQL_ROUTER_APP_NAME ], status = "active" , timeout = TIMEOUT , idle_period = 30
190
177
)
191
178
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
-
203
179
logger .info ("Ensure continuous writes after rollback procedure" )
204
180
await ensure_all_units_continuous_writes_incrementing (ops_test )
205
181
@@ -212,31 +188,28 @@ def create_valid_upgrade_charm(charm_file: typing.Union[str, pathlib.Path]) -> N
212
188
213
189
Upgrades require a new snap revision to avoid no-oping.
214
190
"""
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"
217
198
218
199
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 ))
232
201
233
202
234
203
def create_invalid_upgrade_charm (charm_file : typing .Union [str , pathlib .Path ]) -> None :
235
204
"""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"
239
212
240
213
with zipfile .ZipFile (charm_file , mode = "a" ) as charm_zip :
241
214
# 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