Skip to content

Commit

Permalink
entitlements: static_affordances runtime instance property
Browse files Browse the repository at this point in the history
Entitlement.static_affordances need to be a runtime instance property
so that FIPS* can interactively prompt the user with a callable
prior to performing an enable or disable per canonical#1031.

Once the support is there for dynamically calling external functions
FIPS can use util.prompt_for_confirmation before enable or disable
of the service.
  • Loading branch information
blackboxsw committed Apr 18, 2020
1 parent d8b1c3a commit 8072c2a
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 27 deletions.
10 changes: 6 additions & 4 deletions uaclient/entitlements/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ def description(self) -> str:
"""A sentence describing this entitlement"""
pass

# A tuple of 3-tuples with (failure_message, functor, expected_results)
# If any static_affordance does not match expected_results fail with
# <failure_message>. Overridden in livepatch and fips
static_affordances = () # type: Tuple[StaticAffordance, ...]
@property
def static_affordances(self) -> "Tuple[StaticAffordance, ...]":
# A tuple of 3-tuples with (failure_message, callable, expected_result)
# If any static_affordance does not match expected_result, fail with
# <failure_message>. Overridden in livepatch and fips
return ()

def __init__(self, cfg: "Optional[config.UAConfig]" = None) -> None:
"""Setup UAEntitlement instance
Expand Down
26 changes: 16 additions & 10 deletions uaclient/entitlements/fips.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ class FIPSEntitlement(FIPSCommonEntitlement):
"post_enable": ["A reboot is required to complete the install"]
}
origin = "UbuntuFIPS"
static_affordances = (
("Cannot install FIPS on a container", util.is_container, False),
)

@property
def static_affordances(self) -> "Tuple[StaticAffordance, ...]":
return (
("Cannot install FIPS on a container", util.is_container, False),
)


class FIPSUpdatesEntitlement(FIPSCommonEntitlement):
Expand All @@ -81,10 +84,13 @@ class FIPSUpdatesEntitlement(FIPSCommonEntitlement):
}
origin = "UbuntuFIPSUpdates"
description = "Uncertified security updates to FIPS modules"
static_affordances = (
(
"Cannot install FIPS Updates on a container",
util.is_container,
False,
),
)

@property
def static_affordances(self) -> "Tuple[StaticAffordance, ...]":
return (
(
"Cannot install FIPS Updates on a container",
util.is_container,
False,
),
)
22 changes: 13 additions & 9 deletions uaclient/entitlements/livepatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
SNAP_INSTALL_RETRIES = [0.5, 1.0, 5.0]

try:
from typing import Any, Dict, Tuple # noqa: F401
from typing import Any, Callable, Dict, Tuple # noqa: F401

StaticAffordance = Tuple[str, Callable[[], Any], bool]
except ImportError:
# typing isn't available on trusty, so ignore its absence
pass
Expand All @@ -27,14 +29,16 @@ class LivepatchEntitlement(base.UAEntitlement):
title = "Livepatch"
description = "Canonical Livepatch service"

# Use a lambda so we can mock util.is_container in tests
static_affordances = (
(
"Cannot install Livepatch on a container",
lambda: util.is_container(),
False,
),
)
@property
def static_affordances(self) -> "Tuple[StaticAffordance, ...]":
# Use a lambda so we can mock util.is_container in tests
return (
(
"Cannot install Livepatch on a container",
lambda: util.is_container(),
False,
),
)

def enable(self, *, silent_if_inapplicable: bool = False) -> bool:
"""Enable specific entitlement.
Expand Down
4 changes: 0 additions & 4 deletions uaclient/entitlements/tests/test_cis.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ def test_can_enable_true_on_entitlement_inactive(
self, capsys, entitlement
):
"""When entitlement is INACTIVE, can_enable returns True."""
# Unset static affordance container check
entitlement.static_affordances = ()
with mock.patch.object(
entitlement,
"application_status",
Expand All @@ -49,8 +47,6 @@ def fake_platform(key=None):

m_platform_info.side_effect = fake_platform
m_subp.return_value = ("fakeout", "")
# Unset static affordance container check
entitlement.static_affordances = ()

with mock.patch(
M_REPOPATH + "os.path.exists", mock.Mock(return_value=True)
Expand Down

0 comments on commit 8072c2a

Please sign in to comment.