Skip to content

Commit 843f2a8

Browse files
pieqqHook25
andauthored
Fail snap refresh/revert jobs if the snap_update_test.py script fails (bugfix) (#1616)
* Fail snap refresh/revert jobs if the snap_update_test.py script fails Adding `set -eo pipefail` in the snapd refresh/revert jobs that initiate a reboot ensures that: - any failure in the `snap_update_test.py` is not masked by the pipe command (this is achieved by `set -o pipefail`) - any failure at any step of the `command:` field just fails the whole job (this is ensured by `set -e`). This is important to avoid the `reboot` command from being issued if something goes wrong in the script. Fix #1615 * Increase default timeout of the `snap_update_test.py` script Some devices in our test lab are really slow to download and apply snap updates. Increase timeout from 5 minutes to 10 minutes to hopefully help with this. * Revert the use of `set -e` * Indicate a failed job if an exception is caught when running snapd command When running a snapd revert or refresh command, a SnapdRequestError exception might be raised (for example when the refresh command failed to run within the given time). If this is the case, the script fails, and if it is executed as part of a Checkbox run, a `__result` file is generated and stored in the shared session directory to record the fact that this job failed. When the session is resumed, Checkbox will automatically resume the session and mark this test as failed. * Update unit tests for snap_update_test * Also fail job in case of an AsynException This exception can also be raised when calling snap commands using checkbox_support.snap_utils.snapd.Snapd. * Update providers/base/bin/snap_update_test.py Co-authored-by: Massimiliano <[email protected]> * black is not happy * Fix flake8 --------- Co-authored-by: Massimiliano <[email protected]>
1 parent 399280a commit 843f2a8

File tree

3 files changed

+72
-7
lines changed

3 files changed

+72
-7
lines changed

providers/base/bin/snap_update_test.py

+42-7
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@
2121
import argparse
2222
from pathlib import Path
2323
import json
24+
import os
2425
import sys
2526
import time
2627

2728
from checkbox_support.snap_utils.snapd import Snapd
29+
from checkbox_support.snap_utils.snapd import AsyncException
30+
from checkbox_support.snap_utils.snapd import SnapdRequestError
2831

2932

3033
def guess_snaps() -> list:
@@ -148,11 +151,29 @@ def snap_refresh(self):
148151
self.name, original_revision, self.revision
149152
)
150153
)
151-
response = self.snapd.refresh(
152-
self.name,
153-
channel=self.snap_info.tracking_channel,
154-
revision=self.revision,
155-
)
154+
try:
155+
response = self.snapd.refresh(
156+
self.name,
157+
channel=self.snap_info.tracking_channel,
158+
revision=self.revision,
159+
)
160+
except (SnapdRequestError, AsyncException) as exc:
161+
checkbox_session_dir = os.getenv("PLAINBOX_SESSION_SHARE")
162+
if checkbox_session_dir:
163+
result = {
164+
"outcome": "fail",
165+
"comments": (
166+
"Marking the test as failed because it raised"
167+
" the following:"
168+
)
169+
+ str(exc),
170+
}
171+
result_filename = os.path.join(
172+
checkbox_session_dir, "__result"
173+
)
174+
with open(result_filename, "wt") as result_f:
175+
json.dump(result, result_f)
176+
raise
156177
data["change_id"] = response["change"]
157178
print(
158179
"Snap operation finished. "
@@ -170,7 +191,21 @@ def snap_revert(self):
170191
self.name, destination_rev, original_rev
171192
)
172193
)
173-
response = self.snapd.revert(self.name)
194+
try:
195+
response = self.snapd.revert(self.name)
196+
except (SnapdRequestError, AsyncException) as exc:
197+
checkbox_session_dir = os.getenv("PLAINBOX_SESSION_SHARE")
198+
if checkbox_session_dir:
199+
result = {
200+
"outcome": "fail",
201+
"comments": exc.message,
202+
}
203+
result_filename = os.path.join(
204+
checkbox_session_dir, "__result"
205+
)
206+
with open(result_filename, "wt") as result_f:
207+
json.dump(result, result_f)
208+
raise
174209
data["change_id"] = response["change"]
175210
print(
176211
"Snap operation finished. "
@@ -285,7 +320,7 @@ def main(args):
285320
)
286321
parser.add_argument(
287322
"--timeout",
288-
default=300,
323+
default=600,
289324
help="Timeout for each task, in seconds (default: %(default)s))",
290325
)
291326

providers/base/tests/test_snap_update_test.py

+26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import io
22
import logging
3+
import tempfile
34
import unittest
45
from unittest.mock import patch, mock_open, MagicMock
56

@@ -14,6 +15,8 @@
1415
snap_info_pi_kernel,
1516
)
1617

18+
from checkbox_support.snap_utils.snapd import SnapdRequestError
19+
1720

1821
class SnapUpdateTests(unittest.TestCase):
1922
@classmethod
@@ -179,6 +182,17 @@ def test_snap_refresh_different_revision(self, mock_save_change_info):
179182
snap_update_test.SnapRefreshRevert.snap_refresh(mock_self)
180183
self.assertTrue(mock_self.snapd.refresh.called)
181184

185+
@patch("os.getenv")
186+
def test_snap_refresh_exception(self, mock_getenv):
187+
mock_self = MagicMock()
188+
mock_self.snapd.refresh.side_effect = SnapdRequestError(
189+
"test msg", "test"
190+
)
191+
with self.assertRaises(SnapdRequestError):
192+
with tempfile.TemporaryDirectory() as tmpdirname:
193+
mock_getenv.return_value = tmpdirname
194+
snap_update_test.SnapRefreshRevert.snap_refresh(mock_self)
195+
182196
@patch("snap_update_test.Snapd.revert")
183197
@patch("snap_update_test.load_change_info")
184198
@patch("snap_update_test.save_change_info")
@@ -190,6 +204,18 @@ def test_snap_revert(
190204
self.assertTrue(snap_update_test.load_change_info.called)
191205
self.assertTrue(snap_update_test.save_change_info.called)
192206

207+
@patch("os.getenv")
208+
@patch("snap_update_test.load_change_info")
209+
def test_snap_revert_exception(self, mock_load_change_info, mock_getenv):
210+
mock_self = MagicMock()
211+
mock_self.snapd.revert.side_effect = SnapdRequestError(
212+
"test msg", "test"
213+
)
214+
with self.assertRaises(SnapdRequestError):
215+
with tempfile.TemporaryDirectory() as tmpdirname:
216+
mock_getenv.return_value = tmpdirname
217+
snap_update_test.SnapRefreshRevert.snap_revert(mock_self)
218+
193219
def test_verify_invalid(self):
194220
mock_self = MagicMock()
195221
with self.assertRaises(SystemExit):

providers/base/units/snapd/jobs.pxu

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ requires:
3232
(snap_revision_info.name == "{name}") and snap_revision_info.stable_rev != snap_revision_info.original_installed_rev
3333
manifest.need_{type}_snap_update_test == "True"
3434
command:
35+
set -o pipefail
3536
path="$PLAINBOX_SESSION_SHARE/{name}_snap_revision_info"
3637
logpath="$PLAINBOX_SESSION_SHARE/snap-refresh-{type}-{name}-to-stable-rev.log"
3738
snap_update_test.py --refresh --revision {stable_rev} --info-path "$path" {name} | tee "$logpath"
@@ -81,6 +82,7 @@ category_id: snapd
8182
user: root
8283
depends: snapd/snap-verify-after-refresh-{type}-{name}-to-stable-rev
8384
command:
85+
set -o pipefail
8486
path="$PLAINBOX_SESSION_SHARE/{name}_snap_revision_info"
8587
logpath="$PLAINBOX_SESSION_SHARE/snap-revert-{type}-{name}-from-stable-rev.log"
8688
snap_update_test.py --revert --info-path "$path" {name} | tee "$logpath"
@@ -143,6 +145,7 @@ requires:
143145
(snap_revision_info.name == "{name}") and snap_revision_info.base_rev != snap_revision_info.original_installed_rev
144146
manifest.need_{type}_snap_update_test == "True"
145147
command:
148+
set -o pipefail
146149
path="$PLAINBOX_SESSION_SHARE/{name}_snap_revision_info"
147150
logpath="$PLAINBOX_SESSION_SHARE/snap-refresh-{type}-{name}-to-base-rev.log"
148151
snap_update_test.py --refresh --revision {base_rev} --info-path "$path" {name} | tee "$logpath"
@@ -192,6 +195,7 @@ category_id: snapd
192195
user: root
193196
depends: snapd/snap-verify-after-refresh-{type}-{name}-to-base-rev
194197
command:
198+
set -o pipefail
195199
path="$PLAINBOX_SESSION_SHARE/{name}_snap_revision_info"
196200
logpath="$PLAINBOX_SESSION_SHARE/snap-revert-{type}-{name}-from-base-rev.log"
197201
snap_update_test.py --revert --info-path "$path" {name} | tee "$logpath"

0 commit comments

Comments
 (0)