Don't list UA services that are not entitled
Instead of only checking if a given UA service is available, we now also check if it is entitled. - the available field for a service refers to its availability on the current machine (e.g. on Focal running on a amd64 CPU) ; whereas - the entitled field tells us if the contract covers the service. Therefore, we need to make sure that we only list the services that are both "available" and "entitled". Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
parent
229e364956
commit
7dfe722686
|
@ -6,7 +6,7 @@
|
|||
{
|
||||
"name": "cis",
|
||||
"description": "Center for Internet Security Audit Tools",
|
||||
"entitled": "yes",
|
||||
"entitled": "no",
|
||||
"auto_enabled": "no",
|
||||
"available": "yes"
|
||||
},
|
||||
|
@ -15,7 +15,7 @@
|
|||
"description": "UA Apps: Extended Security Maintenance (ESM)",
|
||||
"entitled": "yes",
|
||||
"auto_enabled": "yes",
|
||||
"available": "yes"
|
||||
"available": "no"
|
||||
},
|
||||
{
|
||||
"name": "esm-infra",
|
||||
|
|
|
@ -78,7 +78,8 @@ class UbuntuAdvantageController(SubiquityTuiController):
|
|||
""" Asynchronously check the token passed as an argument. """
|
||||
async def inner() -> None:
|
||||
try:
|
||||
svcs = await self.ua_interface.get_avail_services(token=token)
|
||||
svcs = await \
|
||||
self.ua_interface.get_activable_services(token=token)
|
||||
except InvalidUATokenError:
|
||||
if isinstance(self.ui.body, UbuntuAdvantageView):
|
||||
self.ui.body.show_invalid_token()
|
||||
|
@ -90,7 +91,7 @@ class UbuntuAdvantageController(SubiquityTuiController):
|
|||
self.ui.body.show_unknown_error()
|
||||
else:
|
||||
if isinstance(self.ui.body, UbuntuAdvantageView):
|
||||
self.ui.body.show_available_services(svcs)
|
||||
self.ui.body.show_activable_services(svcs)
|
||||
|
||||
self._check_task = schedule_task(inner())
|
||||
|
||||
|
|
|
@ -125,24 +125,26 @@ class TestUAClientUAInterfaceStrategy(unittest.TestCase):
|
|||
|
||||
class TestUAInterface(unittest.TestCase):
|
||||
|
||||
def test_mocked_get_avail_services(self):
|
||||
def test_mocked_get_activable_services(self):
|
||||
strategy = MockedUAInterfaceStrategy(scale_factor=1_000_000)
|
||||
interface = UAInterface(strategy)
|
||||
|
||||
with self.assertRaises(InvalidUATokenError):
|
||||
run_coro(interface.get_avail_services(token="invalidToken"))
|
||||
run_coro(interface.get_activable_services(token="invalidToken"))
|
||||
# Tokens starting with "f" in dry-run mode simulate an "internal"
|
||||
# error.
|
||||
with self.assertRaises(CheckSubscriptionError):
|
||||
run_coro(interface.get_avail_services(token="failure"))
|
||||
run_coro(interface.get_activable_services(token="failure"))
|
||||
|
||||
# Tokens starting with "x" is dry-run mode simulate an expired token.
|
||||
with self.assertRaises(ExpiredUATokenError):
|
||||
run_coro(interface.get_avail_services(token="xpiredToken"))
|
||||
run_coro(interface.get_activable_services(token="xpiredToken"))
|
||||
|
||||
# Other tokens are considered valid in dry-run mode.
|
||||
services = run_coro(interface.get_avail_services(token="validToken"))
|
||||
services = run_coro(
|
||||
interface.get_activable_services(token="validToken"))
|
||||
for service in services:
|
||||
self.assertIn("name", service)
|
||||
self.assertIn("description", service)
|
||||
self.assertTrue(service["available"])
|
||||
self.assertEqual(service["available"], "yes")
|
||||
self.assertEqual(service["entitled"], "yes")
|
||||
|
|
|
@ -147,9 +147,9 @@ class UAInterface:
|
|||
""" Return a dictionary containing the subscription information. """
|
||||
return await self.strategy.query_info(token)
|
||||
|
||||
async def get_avail_services(self, token: str) -> List[dict]:
|
||||
""" Return a list of available services for the subscription
|
||||
associated with the token provided.
|
||||
async def get_activable_services(self, token: str) -> List[dict]:
|
||||
""" Return a list of activable services (i.e. services that are
|
||||
entitled to the subscription and available on the current hardware).
|
||||
"""
|
||||
info = await self.get_subscription(token)
|
||||
|
||||
|
@ -157,8 +157,12 @@ class UAInterface:
|
|||
if expiration.timestamp() <= dt.utcnow().timestamp():
|
||||
raise ExpiredUATokenError(token, expires=info["expires"])
|
||||
|
||||
def is_avail_service(service: dict) -> bool:
|
||||
# TODO do we need to check for service["entitled"] as well?
|
||||
return service["available"] == "yes"
|
||||
def is_activable_service(service: dict) -> bool:
|
||||
# - the available field for a service refers to its availability on
|
||||
# the current machine (e.g. on Focal running on a amd64 CPU) ;
|
||||
# whereas
|
||||
# - the entitled field tells us if the contract covers the service.
|
||||
return service["available"] == "yes" \
|
||||
and service["entitled"] == "yes"
|
||||
|
||||
return [svc for svc in info["services"] if is_avail_service(svc)]
|
||||
return [svc for svc in info["services"] if is_activable_service(svc)]
|
||||
|
|
|
@ -189,16 +189,16 @@ class UbuntuAdvantageView(BaseView):
|
|||
self.remove_overlay()
|
||||
self.show_stretchy_overlay(ContinueAnywayWidget(self))
|
||||
|
||||
def show_available_services(self, services: List[dict]) -> None:
|
||||
""" Display an overlay with the list of services that will be enabled
|
||||
via Ubuntu Advantage subscription. After the user confirms, the next we
|
||||
will quit the current view and move on. """
|
||||
def show_activable_services(self, services: List[dict]) -> None:
|
||||
""" Display an overlay with the list of services that can be enabled
|
||||
via Ubuntu Advantage subscription. After the user confirms, we will
|
||||
quit the current view and move on. """
|
||||
self.remove_overlay()
|
||||
self.show_stretchy_overlay(ShowServicesWidget(self, services))
|
||||
|
||||
|
||||
class ShowServicesWidget(Stretchy):
|
||||
""" Widget to show the available services for UA subscription. """
|
||||
""" Widget to show the activable services for UA subscription. """
|
||||
def __init__(self, parent: UbuntuAdvantageView,
|
||||
services: List[dict]) -> None:
|
||||
""" Initializes the widget by including the list of services as a
|
||||
|
@ -207,8 +207,8 @@ class ShowServicesWidget(Stretchy):
|
|||
|
||||
ok = ok_btn(label=_("OK"), on_press=self.ok)
|
||||
|
||||
title = _("Available Services")
|
||||
header = _("List of services that are available through your "
|
||||
title = _("Activable Services")
|
||||
header = _("List of services that are activable through your "
|
||||
"Ubuntu Advantage subscription:")
|
||||
|
||||
widgets: List[Widget] = [
|
||||
|
|
Loading…
Reference in New Issue