def static_affordances(self) -> "Tuple[StaticAffordance, ...]":
        # Use a lambda so we can mock util.is_container in tests
        from uaclient.entitlements.livepatch import LivepatchEntitlement

        livepatch_ent = LivepatchEntitlement(self.cfg)
        enabled_status = status.ApplicationStatus.ENABLED

        is_livepatch_enabled = bool(
            livepatch_ent.application_status()[0] == enabled_status
        )

        return (
            (
                "Cannot install {} on a container".format(self.title),
                lambda: util.is_container(),
                False,
            ),
            (
                "Cannot enable {} when Livepatch is enabled".format(
                    self.title
                ),
                lambda: is_livepatch_enabled,
                False,
            ),
        )
Exemple #2
0
 def test_can_enable_false_on_unsupported_min_kernel_version(
     self,
     _m_is_container,
     _m_livepatch_status,
     _m_fips_status,
     kernel_version,
     meets_min_version,
     entitlement,
 ):
     """When on an unsupported kernel version, can_enable returns False."""
     unsupported_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_kernel["kernel"] = kernel_version
     with mock.patch("uaclient.util.get_platform_info") as m_platform:
         m_platform.return_value = unsupported_kernel
         entitlement = LivepatchEntitlement(entitlement.cfg)
         if meets_min_version:
             assert (True, None) == entitlement.can_enable()
         else:
             result, reason = entitlement.can_enable()
             assert False is result
             assert CanEnableFailureReason.INAPPLICABLE == reason.reason
             msg = ("Livepatch is not available for kernel {}.\n"
                    "Minimum kernel version required: 4.4.".format(
                        kernel_version))
             assert msg == reason.message.msg
 def test_can_enable_false_on_unsupported_min_kernel_version(
     self,
     _m_is_container,
     kernel_version,
     meets_min_version,
     capsys,
     entitlement,
 ):
     """"When on an unsupported kernel version, can_enable returns False."""
     unsupported_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_kernel["kernel"] = kernel_version
     with mock.patch("uaclient.util.get_platform_info") as m_platform:
         m_platform.return_value = unsupported_kernel
         entitlement = LivepatchEntitlement(entitlement.cfg)
         if meets_min_version:
             assert entitlement.can_enable()
         else:
             assert not entitlement.can_enable()
     if meets_min_version:
         msg = ""
     else:
         msg = (
             "Livepatch is not available for kernel {}.\n"
             "Minimum kernel version required: 4.4\n".format(kernel_version)
         )
     assert (msg, "") == capsys.readouterr()
 def test_contract_status_entitled(self, tmpdir):
     """The contract_status returns ENTITLED when entitled is True."""
     cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
     cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
     cfg.write_cache('machine-access-livepatch',
                     dict(LIVEPATCH_RESOURCE_ENTITLED))
     entitlement = LivepatchEntitlement(cfg)
     assert status.ENTITLED == entitlement.contract_status()
    def test_can_enable_false_on_containers(self, tmpdir):
        """When is_container is True, can_enable returns False."""
        cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
        cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
        cfg.write_cache('machine-access-livepatch',
                        dict(LIVEPATCH_RESOURCE_ENTITLED))
        entitlement = LivepatchEntitlement(cfg)

        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
            with mock.patch('uaclient.util.get_platform_info') as m_platform:
                with mock.patch('uaclient.util.is_container') as m_container:
                    with mock.patch(M_GETUID, return_value=0):
                        m_platform.return_value = PLATFORM_INFO_SUPPORTED
                        m_container.return_value = True
                        entitlement = LivepatchEntitlement(
                            entitlement.cfg)
                        assert not entitlement.can_enable()
        msg = 'Cannot install Livepatch on a container\n'
        assert msg == m_stdout.getvalue()
 def test_can_enable_false_on_containers(self, capsys, entitlement):
     """When is_container is True, can_enable returns False."""
     with mock.patch("uaclient.util.get_platform_info") as m_platform:
         with mock.patch("uaclient.util.is_container") as m_container:
             m_platform.return_value = PLATFORM_INFO_SUPPORTED
             m_container.return_value = True
             entitlement = LivepatchEntitlement(entitlement.cfg)
             assert not entitlement.can_enable()
     msg = "Cannot install Livepatch on a container\n"
     assert (msg, "") == capsys.readouterr()
Exemple #7
0
def entitlement(tmpdir):
    """
    A pytest fixture to create a LivepatchEntitlement with some default config

    (Uses the tmpdir fixture for the underlying config cache.)
    """
    cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
    cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
    cfg.write_cache('machine-access-livepatch',
                    dict(LIVEPATCH_RESOURCE_ENTITLED))
    return LivepatchEntitlement(cfg)
    def test_can_enable_false_on_unsupported_architecture(self, tmpdir):
        """"When on an unsupported architecture, can_enable returns False."""
        cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
        cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
        cfg.write_cache('machine-access-livepatch',
                        dict(LIVEPATCH_RESOURCE_ENTITLED))
        entitlement = LivepatchEntitlement(cfg)

        unsupported_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
        unsupported_kernel['arch'] = 'ppc64le'
        with mock.patch('uaclient.util.get_platform_info') as m_platform:
            with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
                with mock.patch(M_GETUID, return_value=0):
                    m_platform.return_value = unsupported_kernel
                    entitlement = LivepatchEntitlement(
                        entitlement.cfg)
                    assert not entitlement.can_enable()
        msg = ('Livepatch is not available for platform ppc64le.\n'
               'Supported platforms are: x86_64\n\n')
        assert msg == m_stdout.getvalue()
    def test_contract_status_unentitled(self, tmpdir):
        """The contract_status returns NONE when entitled is False."""
        livepatch_unentitled = copy.deepcopy(dict(LIVEPATCH_RESOURCE_ENTITLED))

        # Make livepatch resource access report not entitled
        livepatch_unentitled['entitlement']['entitled'] = False
        cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
        cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
        cfg.write_cache('machine-access-livepatch', livepatch_unentitled)
        entitlement = LivepatchEntitlement(cfg)
        assert status.NONE == entitlement.contract_status()
Exemple #10
0
 def test_can_enable_false_on_containers(self, entitlement):
     """When is_container is True, can_enable returns False."""
     with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
         with mock.patch('uaclient.util.get_platform_info') as m_platform:
             with mock.patch('uaclient.util.is_container') as m_container:
                 m_platform.return_value = PLATFORM_INFO_SUPPORTED
                 m_container.return_value = True
                 entitlement = LivepatchEntitlement(entitlement.cfg)
                 assert not entitlement.can_enable()
     msg = 'Cannot install Livepatch on a container\n'
     assert msg == m_stdout.getvalue()
Exemple #11
0
 def test_can_enable_false_on_unsupported_kernel_flavor(self, entitlement):
     """"When on an unsupported kernel, can_enable returns False."""
     unsupported_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_kernel['kernel'] = '4.4.0-140-notgeneric'
     with mock.patch('uaclient.util.get_platform_info') as m_platform:
         with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
             m_platform.return_value = unsupported_kernel
             entitlement = LivepatchEntitlement(entitlement.cfg)
             assert not entitlement.can_enable()
     msg = ('Livepatch is not available for kernel 4.4.0-140-notgeneric.\n'
            'Supported flavors are: generic, lowlatency\n')
     assert msg == m_stdout.getvalue()
Exemple #12
0
 def test_can_enable_false_on_unsupported_kernel_min_version(
         self, _m_is_container, capsys, entitlement):
     """"False when on a kernel less or equal to minKernelVersion."""
     unsupported_min_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_min_kernel["kernel"] = "4.2.9-00-generic"
     with mock.patch("uaclient.util.get_platform_info") as m_platform:
         m_platform.return_value = unsupported_min_kernel
         entitlement = LivepatchEntitlement(entitlement.cfg)
         assert not entitlement.can_enable()
     msg = ("Livepatch is not available for kernel 4.2.9-00-generic.\n"
            "Minimum kernel version required: 4.4\n")
     assert (msg, "") == capsys.readouterr()
 def test_enable_does_not_install_livepatch_snap_when_present(
         self, m_can_enable, m_which, m_subp, tmpdir):
     """Do not attempt to install livepatch snap when it is present."""
     cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
     cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
     cfg.write_cache('machine-access-livepatch',
                     dict(LIVEPATCH_RESOURCE_ENTITLED))
     entitlement = LivepatchEntitlement(cfg)
     with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
         assert entitlement.enable()
     assert self.mocks_config == m_subp.call_args_list
     assert 'Canonical livepatch enabled.\n' == m_stdout.getvalue()
Exemple #14
0
 def test_can_enable_false_on_containers(self, m_is_container, capsys,
                                         entitlement):
     """When is_container is True, can_enable returns False."""
     unsupported_min_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_min_kernel["kernel"] = "4.2.9-00-generic"
     with mock.patch("uaclient.util.get_platform_info") as m_platform:
         m_platform.return_value = unsupported_min_kernel
         m_is_container.return_value = True
         entitlement = LivepatchEntitlement(entitlement.cfg)
         assert not entitlement.can_enable()
     msg = "Cannot install Livepatch on a container\n"
     assert (msg, "") == capsys.readouterr()
Exemple #15
0
 def test_can_enable_false_on_unsupported_kernel_flavor(
         self, _m_is_container, capsys, entitlement):
     """"When on an unsupported kernel, can_enable returns False."""
     unsupported_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_kernel["kernel"] = "4.4.0-140-notgeneric"
     with mock.patch("uaclient.util.get_platform_info") as m_platform:
         m_platform.return_value = unsupported_kernel
         entitlement = LivepatchEntitlement(entitlement.cfg)
         assert not entitlement.can_enable()
     msg = ("Livepatch is not available for kernel 4.4.0-140-notgeneric.\n"
            "Supported flavors are: generic, lowlatency\n")
     assert (msg, "") == capsys.readouterr()
Exemple #16
0
 def test_can_enable_false_on_unsupported_kernel_min_version(
         self, entitlement):
     """"False when on a kernel less or equal to minKernelVersion."""
     unsupported_min_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_min_kernel['kernel'] = '4.2.9-00-generic'
     with mock.patch('uaclient.util.get_platform_info') as m_platform:
         with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
             m_platform.return_value = unsupported_min_kernel
             entitlement = LivepatchEntitlement(entitlement.cfg)
             assert not entitlement.can_enable()
     msg = ('Livepatch is not available for kernel 4.2.9-00-generic.\n'
            'Minimum kernel version required: 4.3\n')
     assert msg == m_stdout.getvalue()
Exemple #17
0
 def test_can_enable_false_on_containers(self, m_is_container,
                                         _m_livepatch_status,
                                         _m_fips_status, entitlement):
     """When is_container is True, can_enable returns False."""
     unsupported_min_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_min_kernel["kernel"] = "4.2.9-00-generic"
     with mock.patch("uaclient.util.get_platform_info") as m_platform:
         m_platform.return_value = unsupported_min_kernel
         m_is_container.return_value = True
         entitlement = LivepatchEntitlement(entitlement.cfg)
         result, reason = entitlement.can_enable()
         assert False is result
         assert CanEnableFailureReason.INAPPLICABLE == reason.reason
         msg = "Cannot install Livepatch on a container."
         assert msg == reason.message.msg
Exemple #18
0
 def test_can_enable_false_on_unsupported_kernel_min_version(
         self, _m_is_container, _m_livepatch_status, _m_fips_status,
         entitlement):
     """False when on a kernel less or equal to minKernelVersion."""
     unsupported_min_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_min_kernel["kernel"] = "4.2.9-00-generic"
     with mock.patch("uaclient.util.get_platform_info") as m_platform:
         m_platform.return_value = unsupported_min_kernel
         entitlement = LivepatchEntitlement(entitlement.cfg)
         result, reason = entitlement.can_enable()
         assert False is result
         assert CanEnableFailureReason.INAPPLICABLE == reason.reason
         msg = ("Livepatch is not available for kernel 4.2.9-00-generic.\n"
                "Minimum kernel version required: 4.4.")
         assert msg == reason.message.msg
Exemple #19
0
 def test_can_enable_false_on_unsupported_kernel_flavor(
         self, _m_is_container, _m_livepatch_status, _m_fips_status,
         entitlement):
     """When on an unsupported kernel, can_enable returns False."""
     unsupported_kernel = copy.deepcopy(dict(PLATFORM_INFO_SUPPORTED))
     unsupported_kernel["kernel"] = "4.4.0-140-notgeneric"
     with mock.patch("uaclient.util.get_platform_info") as m_platform:
         m_platform.return_value = unsupported_kernel
         entitlement = LivepatchEntitlement(entitlement.cfg)
         result, reason = entitlement.can_enable()
         assert False is result
         assert CanEnableFailureReason.INAPPLICABLE == reason.reason
         msg = (
             "Livepatch is not available for kernel 4.4.0-140-notgeneric.\n"
             "Supported flavors are: generic, lowlatency.")
         assert msg == reason.message.msg
 def test_enable_false_when_can_enable_false(
         self, m_can_enable, caplog_text, tmpdir):
     """When can_enable returns False enable returns False."""
     cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
     cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
     cfg.write_cache('machine-access-livepatch',
                     dict(LIVEPATCH_RESOURCE_ENTITLED))
     entitlement = LivepatchEntitlement(cfg)
     with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
         assert not entitlement.enable()
     info_level_logs = [  # see uaclient/conftest.py
         line for line in caplog_text().splitlines()
         if 'DEBUG' not in line]
     assert [] == info_level_logs
     assert '' == m_stdout.getvalue()  # No additional prints
     assert [mock.call()] == m_can_enable.call_args_list
    def test_can_enable_true_on_entitlement_inactive(self, tmpdir):
        """When operational status is INACTIVE, can_enable returns True."""
        cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
        cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
        cfg.write_cache('machine-access-livepatch',
                        dict(LIVEPATCH_RESOURCE_ENTITLED))
        entitlement = LivepatchEntitlement(cfg)

        with mock.patch('uaclient.util.get_platform_info') as m_platform:
            with mock.patch('sys.stderr', new_callable=StringIO) as m_stdout:
                with mock.patch('uaclient.util.is_container') as m_container:
                    with mock.patch(M_GETUID, return_value=0):
                        m_platform.return_value = PLATFORM_INFO_SUPPORTED
                        m_container.return_value = False
                        assert entitlement.can_enable()
        assert '' == m_stdout.getvalue()
        assert [mock.call()] == m_container.call_args_list
    def test_operational_status_inapplicable_on_checked_affordances(
            self, tmpdir):
        """The operational_status details failed check_affordances."""
        livepatch_bionic = copy.deepcopy(dict(LIVEPATCH_RESOURCE_ENTITLED))
        livepatch_bionic['entitlement']['affordances']['series'] = ['bionic']
        cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
        cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
        cfg.write_cache('machine-access-livepatch',
                        dict(LIVEPATCH_RESOURCE_ENTITLED))
        entitlement = LivepatchEntitlement(cfg)
        entitlement.cfg.write_cache(
            'machine-access-livepatch', livepatch_bionic)

        with mock.patch('uaclient.util.get_platform_info') as m_platform_info:
            m_platform_info.return_value = PLATFORM_INFO_SUPPORTED
            op_status, details = entitlement.operational_status()
        assert op_status == status.INAPPLICABLE
        assert 'Livepatch is not available for Ubuntu xenial.' == details
 def test_enable_installs_livepatch_snap_when_absent(
         self, m_can_enable, m_which, m_subp, tmpdir):
     """Install canonical-livepatch snap when not present on the system."""
     cfg = config.UAConfig(cfg={'data_dir': tmpdir.strpath})
     cfg.write_cache('machine-token', dict(LIVEPATCH_MACHINE_TOKEN))
     cfg.write_cache('machine-access-livepatch',
                     dict(LIVEPATCH_RESOURCE_ENTITLED))
     entitlement = LivepatchEntitlement(cfg)
     with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
         assert entitlement.enable()
     assert self.mocks_install + self.mocks_config in m_subp.call_args_list
     msg = ('Installing snapd...\n'
            'Installing canonical-livepatch snap...\n'
            'Canonical livepatch enabled.\n')
     assert msg == m_stdout.getvalue()
     expected_calls = [mock.call('/snap/bin/canonical-livepatch'),
                       mock.call('snap')]
     assert expected_calls == m_which.call_args_list