From 1f9d824e4603e5c8785dc795a11c5d99f8177d15 Mon Sep 17 00:00:00 2001 From: Olivier Gayot Date: Wed, 7 Jun 2023 16:18:50 +0200 Subject: [PATCH] drivers: fix empty list of drivers shown when it has not yet been retrieved The /drivers GET endpoint is supposed to have {"drivers": null} when the list of drivers has not (yes) been retrieved. However, this behavior got broken by the following patch: 66c82b322 drivers: query again list of drivers if the source variant changes .. which resets the drivers variable to an empty list when querying the list of drivers (this happens automatically when the user submits on the source screen). Therefore, instead of getting {"drivers": null}, we would get {"drivers": []} which has a different meaning. The patch also incorrectly declared the drivers variable in the initializer (not taking None into account). The variable was actually already declared as a class variable with the right type. Fixed by resetting the variable to None when re-querying the list of drivers and dropped the class variable in favor of the instance variable (with the right type this time). Signed-off-by: Olivier Gayot --- subiquity/server/controllers/drivers.py | 8 ++++---- subiquity/tests/api/test_api.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/subiquity/server/controllers/drivers.py b/subiquity/server/controllers/drivers.py index 4681c5f9..21660355 100644 --- a/subiquity/server/controllers/drivers.py +++ b/subiquity/server/controllers/drivers.py @@ -48,8 +48,6 @@ class DriversController(SubiquityController): } autoinstall_default = {"install": False} - drivers: Optional[List[str]] = None - def __init__(self, app) -> None: super().__init__(app) self.ubuntu_drivers: Optional[UbuntuDriversInterface] = None @@ -57,7 +55,9 @@ class DriversController(SubiquityController): self._list_drivers_task: Optional[asyncio.Task] = None self.list_drivers_done_event = asyncio.Event() - self.drivers: List[str] = [] + # None means that the list has not (yet) been retrieved whereas an + # empty list means that no drivers are available. + self.drivers: Optional[List[str]] = None def make_autoinstall(self): return { @@ -84,7 +84,7 @@ class DriversController(SubiquityController): self.ubuntu_drivers = get_ubuntu_drivers_interface(self.app) - self.drivers = [] + self.drivers = None self.list_drivers_done_event.clear() if self._list_drivers_task is not None: self._list_drivers_task.cancel() diff --git a/subiquity/tests/api/test_api.py b/subiquity/tests/api/test_api.py index bf0b3f0c..b9f97074 100644 --- a/subiquity/tests/api/test_api.py +++ b/subiquity/tests/api/test_api.py @@ -1667,6 +1667,21 @@ class TestDrivers(TestAPI): async def test_desktop_source(self): await self._test_source('ubuntu-desktop', 'nvidia-driver-510') + @timeout() + async def test_listing_ongoing(self): + ''' Ensure that the list of drivers returned by /drivers is null while + the list has not been retrieved. ''' + async with start_server('examples/simple.json') as inst: + resp = await inst.get('/drivers', wait=False) + self.assertIsNone(resp['drivers']) + + # POSTing to /source will restart the retrieval operation. + await inst.post('/source', source_id='ubuntu-server', + search_drivers=True) + + resp = await inst.get('/drivers', wait=False) + self.assertIsNone(resp['drivers']) + class TestSource(TestAPI): @timeout()