Beispiel #1
0
class TestMain(unittest.TestCase):

    class AskToContinueMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return

    eula_dir = os.path.realpath(os.path.join(os.path.dirname(__file__),
                                             "..", "data", "version-independent"))

    @unit_tests.mock(utils, "ask_to_continue", AskToContinueMocked())
    @unit_tests.mock(utils, "DATA_DIR", eula_dir)
    def test_user_to_accept_eula(self):
        main.user_to_accept_eula()

    class GetFileContentMocked(unit_tests.MockFunction):
        def __call__(self, filename):
            return utils.get_file_content_orig(unit_tests.NONEXISTING_FILE)

    class GetLoggerMocked(unit_tests.MockFunction):
        def __init__(self):
            self.info_msgs = []
            self.critical_msgs = []

        def __call__(self, msg):
            return self

        def critical(self, msg):
            self.critical_msgs.append(msg)
            raise SystemExit(1)

        def info(self, msg):
            pass

        def debug(self, msg):
            pass

    @unit_tests.mock(main.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "ask_to_continue", AskToContinueMocked())
    @unit_tests.mock(utils, "get_file_content", GetFileContentMocked())
    def test_user_to_accept_eula_nonexisting_file(self):
        self.assertRaises(SystemExit, main.user_to_accept_eula)
        self.assertEqual(len(main.logging.getLogger.critical_msgs), 1)

    @unit_tests.mock(utils.changed_pkgs_control, "restore_pkgs", unit_tests.CountableMockObject())
    @unit_tests.mock(redhatrelease.system_release_file, "restore", unit_tests.CountableMockObject())
    @unit_tests.mock(redhatrelease.yum_conf, "restore", unit_tests.CountableMockObject())
    @unit_tests.mock(subscription, "rollback", unit_tests.CountableMockObject())
    def test_rollback_changes(self):
        main.rollback_changes()
        self.assertEqual(utils.changed_pkgs_control.restore_pkgs.called, 1)
        self.assertEqual(redhatrelease.system_release_file.restore.called, 1)
        self.assertEqual(redhatrelease.yum_conf.restore.called, 1)
        self.assertEqual(subscription.rollback.called, 1)
Beispiel #2
0
class TestMain(unittest.TestCase):
    class AskToContinueMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return

    eula_dir = os.path.realpath(
        os.path.join(os.path.dirname(__file__), "..", "data",
                     "version-independent"))

    @unit_tests.mock(utils, "ask_to_continue", AskToContinueMocked())
    @unit_tests.mock(utils, "DATA_DIR", eula_dir)
    def test_user_to_accept_eula(self):
        main.user_to_accept_eula()

    class GetFileContentMocked(unit_tests.MockFunction):
        def __call__(self, filename):
            return utils.get_file_content_orig(unit_tests.NONEXISTING_FILE)

    class GetLoggerMocked(unit_tests.MockFunction):
        def __init__(self):
            self.info_msgs = []
            self.critical_msgs = []

        def __call__(self, msg):
            return self

        def task(self, msg):
            pass

        def critical(self, msg):
            self.critical_msgs.append(msg)
            raise SystemExit(1)

        def info(self, msg):
            pass

        def debug(self, msg):
            pass

    class CallOrderMocked(unit_tests.MockFunction):
        calls = OrderedDict()

        def __init__(self, method_name):
            self.method_name = method_name

        def __call__(self, *args):
            self.add_call(self.method_name)
            return args

        @classmethod
        def add_call(cls, method_name):
            if method_name in cls.calls:
                cls.calls[method_name] += 1
            else:
                cls.calls[method_name] = 1

        @classmethod
        def reset(cls):
            cls.calls = OrderedDict()

    @unit_tests.mock(main.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "ask_to_continue", AskToContinueMocked())
    @unit_tests.mock(utils, "get_file_content", GetFileContentMocked())
    def test_user_to_accept_eula_nonexisting_file(self):
        self.assertRaises(SystemExit, main.user_to_accept_eula)
        self.assertEqual(len(main.logging.getLogger.critical_msgs), 1)

    @unit_tests.mock(utils.changed_pkgs_control, "restore_pkgs",
                     unit_tests.CountableMockObject())
    @unit_tests.mock(redhatrelease.system_release_file, "restore",
                     unit_tests.CountableMockObject())
    @unit_tests.mock(redhatrelease.yum_conf, "restore",
                     unit_tests.CountableMockObject())
    @unit_tests.mock(subscription, "rollback",
                     unit_tests.CountableMockObject())
    def test_rollback_changes(self):
        main.rollback_changes()
        self.assertEqual(utils.changed_pkgs_control.restore_pkgs.called, 1)
        self.assertEqual(redhatrelease.system_release_file.restore.called, 1)
        self.assertEqual(redhatrelease.yum_conf.restore.called, 1)
        self.assertEqual(subscription.rollback.called, 1)

    @unit_tests.mock(main.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(tool_opts, "disable_submgr", False)
    @mock_calls(pkghandler, "remove_excluded_pkgs", CallOrderMocked)
    @mock_calls(redhatrelease, "install_release_pkg", CallOrderMocked)
    @mock_calls(redhatrelease.YumConf, "patch", CallOrderMocked)
    @mock_calls(pkghandler, "list_third_party_pkgs", CallOrderMocked)
    @mock_calls(subscription, "install_subscription_manager", CallOrderMocked)
    @mock_calls(subscription, "subscribe_system", CallOrderMocked)
    @mock_calls(repo, "get_rhel_repoids", CallOrderMocked)
    @mock_calls(subscription, "check_needed_repos_availability",
                CallOrderMocked)
    @mock_calls(subscription, "disable_repos", CallOrderMocked)
    @mock_calls(subscription, "enable_repos", CallOrderMocked)
    @mock_calls(subscription, "rename_repo_files", CallOrderMocked)
    def test_pre_ponr_conversion_order_with_rhsm(self):
        self.CallOrderMocked.reset()
        main.pre_ponr_conversion()

        intended_call_order = OrderedDict()
        intended_call_order["remove_excluded_pkgs"] = 1
        intended_call_order["install_release_pkg"] = 1
        intended_call_order["patch"] = 1
        intended_call_order["list_third_party_pkgs"] = 1
        intended_call_order["install_subscription_manager"] = 1
        intended_call_order["subscribe_system"] = 1
        intended_call_order["get_rhel_repoids"] = 1
        intended_call_order["check_needed_repos_availability"] = 1
        intended_call_order["disable_repos"] = 1
        intended_call_order["enable_repos"] = 1
        intended_call_order["rename_repo_files"] = 1

        # Merge the two together like a zipper, creates a tuple which we can assert with - including method call order!
        zipped_call_order = zip(intended_call_order.items(),
                                self.CallOrderMocked.calls.items())
        for expected, actual in zipped_call_order:
            if expected[1] > 0:
                self.assertEqual(expected, actual)

    @unit_tests.mock(main.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(tool_opts, "disable_submgr", False)
    @mock_calls(pkghandler, "remove_excluded_pkgs", CallOrderMocked)
    @mock_calls(redhatrelease, "install_release_pkg", CallOrderMocked)
    @mock_calls(redhatrelease.YumConf, "patch", CallOrderMocked)
    @mock_calls(pkghandler, "list_third_party_pkgs", CallOrderMocked)
    @mock_calls(subscription, "install_subscription_manager", CallOrderMocked)
    @mock_calls(subscription, "subscribe_system", CallOrderMocked)
    @mock_calls(repo, "get_rhel_repoids", CallOrderMocked)
    @mock_calls(subscription, "check_needed_repos_availability",
                CallOrderMocked)
    @mock_calls(subscription, "disable_repos", CallOrderMocked)
    @mock_calls(subscription, "enable_repos", CallOrderMocked)
    @mock_calls(subscription, "rename_repo_files", CallOrderMocked)
    def test_pre_ponr_conversion_order_without_rhsm(self):
        self.CallOrderMocked.reset()
        main.pre_ponr_conversion()

        intended_call_order = OrderedDict()
        intended_call_order["remove_excluded_pkgs"] = 1
        intended_call_order["install_release_pkg"] = 1
        intended_call_order["patch"] = 1
        intended_call_order["list_third_party_pkgs"] = 1

        # Do not expect these to be called - related to RHSM
        intended_call_order["install_subscription_manager"] = 0
        intended_call_order["subscribe_system"] = 0
        intended_call_order["get_rhel_repoids"] = 0
        intended_call_order["check_needed_repos_availability"] = 0
        intended_call_order["disable_repos"] = 0
        intended_call_order["enable_repos"] = 0
        intended_call_order["rename_repo_files"] = 0

        # Merge the two together like a zipper, creates a tuple which we can assert with - including method call order!
        zipped_call_order = zip(intended_call_order.items(),
                                self.CallOrderMocked.calls.items())
        for expected, actual in zipped_call_order:
            if expected[1] > 0:
                self.assertEqual(expected, actual)
class TestSubscription(unittest.TestCase):
    class GetAvailSubsMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return [{
                'name': 'sample',
                'available': True,
                'ends': '31/12/2999',
                'systype': 'sampletype',
                'pool': 'samplepool'
            }]

    class GetNoAvailSubsMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return []

    class GetNoAvailSubsOnceMocked(unit_tests.MockFunction):
        def __init__(self):
            self.empty_last_call = False

        def __call__(self, *args, **kwargs):
            if not self.empty_last_call:
                self.empty_last_call = True
                return []

            self.empty_last_call = False
            return [{
                'name': 'sample',
                'available': True,
                'ends': '31/12/2999',
                'systype': 'sampletype',
                'pool': 'samplepool'
            }]

    class LetUserChooseItemMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return 0

    class GetRegistrationCmdMocked(unit_tests.MockFunction):
        def __call__(self):
            return "subscription-manager register whatever-options"

    class RunSubprocessMocked(unit_tests.MockFunction):
        def __init__(self, tuples=None):
            # you can specify sequence of return (object, return code) as
            # a list of tuple that will be consumed continuosly on the each
            # call; when the list is consumed or it is empty, the default
            # tuple is returned
            self.tuples = tuples
            self.default_tuple = ('output', 0)
            self.called = 0
            self.cmd = ""

        def __call__(self, cmd, *args, **kwargs):
            self.cmd = cmd
            self.called += 1

            if self.tuples:
                return self.tuples.pop(0)
            return self.default_tuple

    class RegisterSystemMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0

        def __call__(self, *args, **kwargs):
            self.called += 1

    class GetLoggerMocked(unit_tests.MockFunction):
        def __init__(self):
            self.info_msgs = []
            self.warning_msgs = []
            self.critical_msgs = []

        def __call__(self, msg):
            return self

        def critical(self, msg):
            self.critical_msgs.append(msg)
            raise SystemExit(1)

        def info(self, msg):
            self.info_msgs.append(msg)

        def warn(self, msg, *args):
            self.warning_msgs.append(msg)

        def warning(self, msg, *args):
            self.warn(msg, *args)

        def debug(self, msg):
            pass

    class IsFileMocked(unit_tests.MockFunction):
        def __init__(self, is_file):
            self.is_file = is_file

        def __call__(self, *args, **kwargs):
            return self.is_file

    class PromptUserMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return True

    class RemoveFileMocked(unit_tests.MockFunction):
        def __init__(self, removed=True):
            self.removed = removed

        def __call__(self, *args, **kwargs):
            return self.removed

    ##########################################################################

    def setUp(self):
        tool_opts.__init__()

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(os.path, "isfile", IsFileMocked(is_file=False))
    def test_rhn_classic_not_exist(self):
        subscription.unregister_from_rhn_classic()
        self.assertEqual(len(subscription.logging.getLogger.info_msgs), 1)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(os.path, "isfile", IsFileMocked(is_file=True))
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(subscription.rhn_reg_file, "remove", RemoveFileMocked())
    def test_rhn_classic_not_exist(self):
        subscription.unregister_from_rhn_classic()
        self.assertEqual(len(subscription.logging.getLogger.info_msgs), 0)
        self.assertEqual(len(subscription.logging.getLogger.warning_msgs), 1)

    def test_get_registration_cmd(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        expected = \
            'subscription-manager register --force --username=user --password="******"'
        self.assertEqual(subscription.get_registration_cmd(), expected)

    @unit_tests.mock(subscription, "get_avail_subs", GetAvailSubsMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_attach_subscription_available(self):
        self.assertEqual(subscription.attach_subscription(), True)

    @unit_tests.mock(subscription, "get_avail_subs", GetNoAvailSubsMocked())
    def test_attach_subscription_none_available(self):
        self.assertEqual(subscription.attach_subscription(), False)

    @unit_tests.mock(subscription, "register_system", RegisterSystemMocked())
    @unit_tests.mock(subscription, "get_avail_subs", GetAvailSubsMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_subscribe_system(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        subscription.subscribe_system()
        self.assertEqual(subscription.register_system.called, 1)

    @unit_tests.mock(subscription, "register_system", RegisterSystemMocked())
    @unit_tests.mock(subscription, "get_avail_subs",
                     GetNoAvailSubsOnceMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_subscribe_system_fail_once(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        subscription.subscribe_system()
        self.assertEqual(subscription.register_system.called, 2)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "run_subprocess",
                     RunSubprocessMocked([("nope", 1)]))
    def test_register_system_fail_non_interactive(self):
        # Check the critical severity is logged when the credentials are given
        # on the cmdline but registration fails
        tool_opts.username = '******'
        tool_opts.password = '******'
        tool_opts.credentials_thru_cli = True
        self.assertRaises(SystemExit, subscription.register_system)
        self.assertEqual(len(subscription.logging.getLogger.critical_msgs), 1)

    @unit_tests.mock(utils, "run_subprocess",
                     RunSubprocessMocked(tuples=[("nope",
                                                  1), ("nope",
                                                       2), ("Success", 0)]))
    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(subscription, "get_registration_cmd",
                     GetRegistrationCmdMocked())
    def test_register_system_fail_interactive(self):
        # Check the function tries to register multiple times without
        # critical log.
        tool_opts.credentials_thru_cli = False
        subscription.register_system()
        self.assertEqual(utils.run_subprocess.called, 3)
        self.assertEqual(len(subscription.logging.getLogger.critical_msgs), 0)

    def test_hiding_password(self):
        test_cmd = 'subscription-manager register --force ' \
                   '--username=jdoe --password="******" --org=0123'
        pswds_to_test = [
            "my favourite password", "\\)(*&^%f %##@^%&*&^(", " ", ""
        ]
        for pswd in pswds_to_test:
            sanitized_cmd = subscription.hide_password(test_cmd % pswd)
            self.assertEqual(
                sanitized_cmd, 'subscription-manager register --force '
                '--username=jdoe --password="******" --org=0123')

    def test_rhsm_serverurl(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        tool_opts.serverurl = 'url'
        expected = \
            'subscription-manager register --force --username=user --password="******" --serverurl="url"'
        self.assertEqual(subscription.get_registration_cmd(), expected)

    class FakeSubscription:
        def __init__(self):
            self.subscription = (
                "Subscription Name: Good subscription\n"
                "Provides:          Something good\n"
                "SKU:               00EEE00EE\n"
                "Contract:          01234567\n"
                "Pool ID:           8aaaa123045897fb564240aa00aa0000\n"
                "Available:         1\n"
                "Suggested:         1\n"
                "Service Level:     Self-icko\n"
                "Service Type:      L1-L3\n"
                "Subscription Type: Standard\n"
                "Ends:              %s\n"
                "System Type:       Virtual\n")
            self.dates_formats = [
                "26.07.2018", "26. 07. 2018", "26/07/2018", "H26.07.2018",
                "26-07-2018", "07.26.2018", "2018/07/26", "2018.07.26",
                "2018-07-26", "2018-26-07", "2018.26.07", "2018/26/07"
            ]

        def __call__(self, date):
            return self.subscription % date

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    def test_parse_sub_date(self):
        # Check that various formats of date don't affect parsing of SKU
        sku = self.FakeSubscription()
        for i in sku.dates_formats:
            self.assertEqual(subscription.parse_sub_attrs(sku(i))["ends"], i)
            self.assertEqual(len(subscription.logging.getLogger.critical_msgs),
                             0)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_unregister_system_successfully(self):
        unregistration_cmd = "subscription-manager unregister"
        subscription.unregister_system()
        self.assertEqual(utils.run_subprocess.called, 1)
        self.assertEqual(utils.run_subprocess.cmd, unregistration_cmd)
        self.assertEqual(len(subscription.logging.getLogger.info_msgs), 2)
        self.assertEqual(len(subscription.logging.getLogger.warning_msgs), 0)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "run_subprocess",
                     RunSubprocessMocked([('output', 1)]))
    def test_unregister_system_fails(self):
        unregistration_cmd = "subscription-manager unregister"
        subscription.unregister_system()
        self.assertEqual(utils.run_subprocess.called, 1)
        self.assertEqual(utils.run_subprocess.cmd, unregistration_cmd)
        self.assertEqual(len(subscription.logging.getLogger.info_msgs), 1)
        self.assertEqual(len(subscription.logging.getLogger.warning_msgs), 1)

    @unit_tests.mock(subscription, "rollback_renamed_repo_files",
                     unit_tests.CountableMockObject())
    @unit_tests.mock(subscription, "unregister_system",
                     unit_tests.CountableMockObject())
    def test_rollback(self):
        subscription.rollback()
        self.assertEqual(subscription.rollback_renamed_repo_files.called, 1)
        self.assertEqual(subscription.unregister_system.called, 1)
Beispiel #4
0
class TestSubscription(unittest.TestCase):
    class IsFileMocked(unit_tests.MockFunction):
        def __init__(self, is_file):
            self.is_file = is_file

        def __call__(self, *args, **kwargs):
            return self.is_file

    class PromptUserMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return True

    class RemoveFileMocked(unit_tests.MockFunction):
        def __init__(self, removed=True):
            self.removed = removed

        def __call__(self, *args, **kwargs):
            return self.removed

    class CallYumCmdMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0
            self.return_code = 0
            self.return_string = "Test output"
            self.fail_once = False
            self.command = None
            self.args = None

        def __call__(self, command, args):
            if self.fail_once and self.called == 0:
                self.return_code = 1
            if self.fail_once and self.called > 0:
                self.return_code = 0
            self.called += 1
            self.command = command
            self.args = args
            return self.return_string, self.return_code

    ##########################################################################

    def setUp(self):
        tool_opts.__init__()

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    def test_get_pool_id(self):
        # Check that we can distill the pool id from the subscription description
        pool_id = subscription.get_pool_id(self.SUBSCRIPTION_DETAILS)

        self.assertEqual(pool_id, "8aaaa123045897fb564240aa00aa0000")

    # Details of one subscription as output by `subscription-manager list --available`
    SUBSCRIPTION_DETAILS = (
        "Subscription Name: Good subscription\n"
        "Provides:          Something good\n"
        "SKU:               00EEE00EE\n"
        "Contract:          01234567\n"
        "Pool ID:           8aaaa123045897fb564240aa00aa0000\n"
        "Available:         1\n"
        "Suggested:         1\n"
        "Service Level:     Self-icko\n"
        "Service Type:      L1-L3\n"
        "Subscription Type: Standard\n"
        "Ends:              2018/26/07\n"
        "System Type:       Virtual\n\n"  # this has changed to Entitlement Type since RHEL 7.8
    )

    @unit_tests.mock(subscription, "unregister_system",
                     unit_tests.CountableMockObject())
    def test_rollback(self):
        subscription.rollback()
        self.assertEqual(subscription.unregister_system.called, 1)

    class LogMocked(unit_tests.MockFunction):
        def __init__(self):
            self.msg = ""

        def __call__(self, msg):
            self.msg += "%s\n" % msg

    @unit_tests.mock(logging.Logger, "info", LogMocked())
    @unit_tests.mock(logging.Logger, "warning", LogMocked())
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(subscription, "get_avail_repos",
                     lambda: ["rhel_x", "rhel_y"])
    def test_check_needed_repos_availability(self):
        subscription.check_needed_repos_availability(["rhel_x"])
        self.assertTrue("Needed RHEL repositories are available." in
                        logging.Logger.info.msg)

        subscription.check_needed_repos_availability(["rhel_z"])
        self.assertTrue(
            "rhel_z repository is not available" in logging.Logger.warning.msg)

    @unit_tests.mock(logging.Logger, "warning", LogMocked())
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(subscription, "get_avail_repos", lambda: [])
    def test_check_needed_repos_availability_no_repo_available(self):
        subscription.check_needed_repos_availability(["rhel"])
        self.assertTrue(
            "rhel repository is not available" in logging.Logger.warning.msg)

    @unit_tests.mock(os.path, "isdir", lambda x: True)
    @unit_tests.mock(os, "listdir", lambda x: [])
    def test_replace_subscription_manager_rpms_not_available(self):
        self.assertRaises(SystemExit,
                          subscription.replace_subscription_manager)

        os.path.isdir = lambda x: False
        os.listdir = lambda x: ["filename"]
        self.assertRaises(SystemExit,
                          subscription.replace_subscription_manager)

    @unit_tests.mock(pkghandler, "get_installed_pkg_objects",
                     lambda _: [namedtuple("Pkg", ["name"])("submgr")])
    @unit_tests.mock(pkghandler, "print_pkg_info", lambda x: None)
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(backup, "remove_pkgs", DumbCallable())
    def test_remove_original_subscription_manager(self):
        subscription.remove_original_subscription_manager()

        self.assertEqual(backup.remove_pkgs.called, 1)

    @unit_tests.mock(
        pkghandler,
        "get_installed_pkg_objects",
        lambda _: [
            namedtuple("Pkg", ["name"])
            ("subscription-manager-initial-setup-addon")
        ],
    )
    @unit_tests.mock(system_info, "version",
                     namedtuple("Version", ["major", "minor"])(8, 5))
    @unit_tests.mock(system_info, "id", "centos")
    @unit_tests.mock(pkghandler, "print_pkg_info", lambda x: None)
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(backup, "remove_pkgs", DumbCallable())
    def test_remove_original_subscription_manager_missing_package_ol_85(self):
        subscription.remove_original_subscription_manager()
        self.assertEqual(backup.remove_pkgs.called, 2)

    @unit_tests.mock(pkghandler, "get_installed_pkg_objects", lambda _: [])
    @unit_tests.mock(subscription, "loggerinst", GetLoggerMocked())
    def test_remove_original_subscription_manager_no_pkgs(self):
        subscription.remove_original_subscription_manager()

        self.assertEqual(len(subscription.loggerinst.info_msgs), 2)
        self.assertTrue(
            "No packages related to subscription-manager installed." in
            subscription.loggerinst.info_msgs[-1])

    @unit_tests.mock(logging.Logger, "info", LogMocked())
    @unit_tests.mock(os.path, "isdir", lambda x: True)
    @unit_tests.mock(os, "listdir", lambda x: ["filename"])
    @unit_tests.mock(
        pkghandler,
        "call_yum_cmd",
        lambda command, args, print_output, enable_repos, disable_repos,
        set_releasever: (None, 0),
    )
    @unit_tests.mock(pkghandler, "filter_installed_pkgs", DumbCallable())
    @unit_tests.mock(pkghandler, "get_pkg_names_from_rpm_paths",
                     DumbCallable())
    @unit_tests.mock(backup.changed_pkgs_control, "track_installed_pkgs",
                     DumbCallable())
    @unit_tests.mock(subscription, "track_installed_submgr_pkgs",
                     DumbCallable())
    def test_install_rhel_subscription_manager(self):
        subscription.install_rhel_subscription_manager()
        self.assertEqual(pkghandler.get_pkg_names_from_rpm_paths.called, 1)
        self.assertTrue("\nPackages installed:\n" in logging.Logger.info.msg)
        self.assertEqual(subscription.track_installed_submgr_pkgs.called, 1)

    @unit_tests.mock(logging.Logger, "warning", LogMocked())
    @unit_tests.mock(os.path, "isdir", lambda x: True)
    @unit_tests.mock(os, "listdir", lambda x: "")
    @unit_tests.mock(subscription, "SUBMGR_RPMS_DIR", "")
    def test_install_rhel_subscription_manager_without_packages(self):
        subscription.install_rhel_subscription_manager()
        self.assertTrue("No RPMs found" in logging.Logger.warning.msg)

    @unit_tests.mock(os, "listdir", lambda x: [":w"])
    @unit_tests.mock(
        pkghandler,
        "call_yum_cmd",
        lambda command, args, print_output, enable_repos, disable_repos,
        set_releasever: (None, 1),
    )
    @unit_tests.mock(pkghandler, "filter_installed_pkgs", lambda x: ["test"])
    @unit_tests.mock(pkghandler, "get_pkg_names_from_rpm_paths",
                     lambda x: ["test"])
    def test_install_rhel_subscription_manager_unable_to_install(self):
        self.assertRaises(SystemExit,
                          subscription.install_rhel_subscription_manager)

    class StoreContentMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0
            self.filename = None
            self.content = None

        def __call__(self, filename, content):
            self.called += 1
            self.filename = filename
            self.content = content
            return True

    class DownloadPkgsMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0
            self.to_return = ["/path/to.rpm"]

        def __call__(self, pkgs, dest, reposdir=None):
            self.called += 1
            self.pkgs = pkgs
            self.dest = dest
            self.reposdir = reposdir
            return self.to_return

    @unit_tests.mock(utils, "store_content_to_file", StoreContentMocked())
    @unit_tests.mock(utils, "download_pkgs", DownloadPkgsMocked())
    def test__download_rhsm_pkgs(self):
        subscription._download_rhsm_pkgs(["testpkg"], "/path/to.repo",
                                         "content")

        self.assertTrue(
            "/path/to.repo" in utils.store_content_to_file.filename)
        self.assertEqual(utils.download_pkgs.called, 1)

        utils.download_pkgs.to_return.append(None)

        self.assertRaises(SystemExit, subscription._download_rhsm_pkgs,
                          ["testpkg"], "/path/to.repo", "content")

    class DownloadPkgMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0
            self.to_return = "/path/to.rpm"

        def __call__(self, pkg, dest, reposdir=None):
            self.called += 1
            self.pkg = pkg
            self.dest = dest
            self.reposdir = reposdir
            return self.to_return
class TestSubscription(unittest.TestCase):
    class GetAvailSubsMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return [
                namedtuple('Sub',
                           ['pool_id', 'sub_raw'])('samplepool',
                                                   'Subscription description')
            ]

    class GetNoAvailSubsMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return []

    class GetNoAvailSubsOnceMocked(unit_tests.MockFunction):
        def __init__(self):
            self.empty_last_call = False

        def __call__(self, *args, **kwargs):
            if not self.empty_last_call:
                self.empty_last_call = True
                return []

            self.empty_last_call = False
            return [
                namedtuple('Sub',
                           ['pool_id', 'sub_raw'])('samplepool',
                                                   'Subscription description')
            ]

    class LetUserChooseItemMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return 0

    class GetRegistrationCmdMocked(unit_tests.MockFunction):
        def __call__(self):
            return "subscription-manager register whatever-options"

    class RunSubprocessMocked(unit_tests.MockFunction):
        def __init__(self, tuples=None):
            # you can specify sequence of return (object, return code) as
            # a list of tuple that will be consumed continuosly on the each
            # call; when the list is consumed or it is empty, the default
            # tuple is returned
            self.tuples = tuples
            self.default_tuple = ('output', 0)
            self.called = 0
            self.cmd = ""

        def __call__(self, cmd, *args, **kwargs):
            self.cmd = cmd
            self.called += 1

            if self.tuples:
                return self.tuples.pop(0)
            return self.default_tuple

    class DumbCallable(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0

        def __call__(self, *args, **kwargs):
            self.called += 1

    class GetLoggerMocked(unit_tests.MockFunction):
        def __init__(self):
            self.task_msgs = []
            self.info_msgs = []
            self.warning_msgs = []
            self.critical_msgs = []
            self.error_msgs = []

        def __call__(self, msg):
            return self

        def critical(self, msg):
            self.critical_msgs.append(msg)
            raise SystemExit(1)

        def error(self, msg):
            self.error_msgs.append(msg)

        def task(self, msg):
            self.task_msgs.append(msg)

        def info(self, msg):
            self.info_msgs.append(msg)

        def warn(self, msg, *args):
            self.warning_msgs.append(msg)

        def warning(self, msg, *args):
            self.warn(msg, *args)

        def debug(self, msg):
            pass

    class IsFileMocked(unit_tests.MockFunction):
        def __init__(self, is_file):
            self.is_file = is_file

        def __call__(self, *args, **kwargs):
            return self.is_file

    class PromptUserMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return True

    class RemoveFileMocked(unit_tests.MockFunction):
        def __init__(self, removed=True):
            self.removed = removed

        def __call__(self, *args, **kwargs):
            return self.removed

    class CallYumCmdMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0
            self.return_code = 0
            self.return_string = "Test output"
            self.fail_once = False
            self.command = None
            self.args = None

        def __call__(self, command, args):
            if self.fail_once and self.called == 0:
                self.return_code = 1
            if self.fail_once and self.called > 0:
                self.return_code = 0
            self.called += 1
            self.command = command
            self.args = args
            return self.return_string, self.return_code

    ##########################################################################

    def setUp(self):
        tool_opts.__init__()

    def test_get_registration_cmd(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        expected = \
            'subscription-manager register --force --username=user --password="******"'
        self.assertEqual(subscription.get_registration_cmd(), expected)

    @unit_tests.mock(subscription, "get_avail_subs", GetAvailSubsMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_attach_subscription_available(self):
        self.assertEqual(subscription.attach_subscription(), True)

    @unit_tests.mock(subscription, "get_avail_subs", GetAvailSubsMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    @unit_tests.mock(tool_opts, "activation_key", "dummy_activate_key")
    def test_attach_subscription_available_with_activation_key(self):
        self.assertEqual(subscription.attach_subscription(), True)

    @unit_tests.mock(subscription, "get_avail_subs", GetNoAvailSubsMocked())
    def test_attach_subscription_none_available(self):
        self.assertEqual(subscription.attach_subscription(), False)

    @unit_tests.mock(subscription, "register_system", DumbCallable())
    @unit_tests.mock(subscription, "get_avail_subs", GetAvailSubsMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_subscribe_system(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        subscription.subscribe_system()
        self.assertEqual(subscription.register_system.called, 1)

    @unit_tests.mock(subscription, "register_system", DumbCallable())
    @unit_tests.mock(subscription, "get_avail_subs",
                     GetNoAvailSubsOnceMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_subscribe_system_fail_once(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        subscription.subscribe_system()
        self.assertEqual(subscription.register_system.called, 2)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "run_subprocess",
                     RunSubprocessMocked([("nope", 1)]))
    def test_register_system_fail_non_interactive(self):
        # Check the critical severity is logged when the credentials are given
        # on the cmdline but registration fails
        tool_opts.username = '******'
        tool_opts.password = '******'
        tool_opts.credentials_thru_cli = True
        self.assertRaises(SystemExit, subscription.register_system)
        self.assertEqual(len(subscription.logging.getLogger.critical_msgs), 1)

    @unit_tests.mock(utils, "run_subprocess",
                     RunSubprocessMocked(tuples=[("nope",
                                                  1), ("nope",
                                                       2), ("Success", 0)]))
    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(subscription, "get_registration_cmd",
                     GetRegistrationCmdMocked())
    def test_register_system_fail_interactive(self):
        # Check the function tries to register multiple times without
        # critical log.
        tool_opts.credentials_thru_cli = False
        subscription.register_system()
        self.assertEqual(utils.run_subprocess.called, 3)
        self.assertEqual(len(subscription.logging.getLogger.critical_msgs), 0)

    def test_hiding_password(self):
        test_cmd = 'subscription-manager register --force ' \
                   '--username=jdoe --password="******" --org=0123'
        pswds_to_test = [
            "my favourite password", "\\)(*&^%f %##@^%&*&^(", " ", ""
        ]
        for pswd in pswds_to_test:
            sanitized_cmd = subscription.hide_password(test_cmd % pswd)
            self.assertEqual(
                sanitized_cmd, 'subscription-manager register --force '
                '--username=jdoe --password="******" --org=0123')

    def test_rhsm_serverurl(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        tool_opts.serverurl = 'url'
        expected = \
            'subscription-manager register --force --username=user --password="******" --serverurl="url"'
        self.assertEqual(subscription.get_registration_cmd(), expected)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    def test_get_pool_id(self):
        # Check that we can distill the pool id from the subscription description
        pool_id = subscription.get_pool_id(self.SUBSCRIPTION_DETAILS)

        self.assertEqual(pool_id, "8aaaa123045897fb564240aa00aa0000")

    # Details of one subscription as output by `subscription-manager list --available`
    SUBSCRIPTION_DETAILS = (
        "Subscription Name: Good subscription\n"
        "Provides:          Something good\n"
        "SKU:               00EEE00EE\n"
        "Contract:          01234567\n"
        "Pool ID:           8aaaa123045897fb564240aa00aa0000\n"
        "Available:         1\n"
        "Suggested:         1\n"
        "Service Level:     Self-icko\n"
        "Service Type:      L1-L3\n"
        "Subscription Type: Standard\n"
        "Ends:              2018/26/07\n"
        "System Type:       Virtual\n\n"  # this has changed to Entitlement Type since RHEL 7.8
    )

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_unregister_system_successfully(self):
        unregistration_cmd = "subscription-manager unregister"
        subscription.unregister_system()
        self.assertEqual(utils.run_subprocess.called, 1)
        self.assertEqual(utils.run_subprocess.cmd, unregistration_cmd)
        self.assertEqual(len(subscription.logging.getLogger.info_msgs), 1)
        self.assertEqual(len(subscription.logging.getLogger.task_msgs), 1)
        self.assertEqual(len(subscription.logging.getLogger.warning_msgs), 0)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "run_subprocess",
                     RunSubprocessMocked([('output', 1)]))
    def test_unregister_system_fails(self):
        unregistration_cmd = "subscription-manager unregister"
        subscription.unregister_system()
        self.assertEqual(utils.run_subprocess.called, 1)
        self.assertEqual(utils.run_subprocess.cmd, unregistration_cmd)
        self.assertEqual(len(subscription.logging.getLogger.info_msgs), 0)
        self.assertEqual(len(subscription.logging.getLogger.task_msgs), 1)
        self.assertEqual(len(subscription.logging.getLogger.warning_msgs), 1)

    @unit_tests.mock(subscription, "unregister_system",
                     unit_tests.CountableMockObject())
    @unit_tests.mock(subscription, "remove_subscription_manager",
                     unit_tests.CountableMockObject())
    def test_rollback(self):
        subscription.rollback()
        self.assertEqual(subscription.unregister_system.called, 1)
        self.assertEqual(subscription.remove_subscription_manager.called, 1)

    class LogMocked(unit_tests.MockFunction):
        def __init__(self):
            self.msg = ""

        def __call__(self, msg):
            self.msg += "%s\n" % msg

    @unit_tests.mock(logger.CustomLogger, "info", LogMocked())
    @unit_tests.mock(logger.CustomLogger, "warning", LogMocked())
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(subscription, "get_avail_repos",
                     lambda: ["rhel_x", "rhel_y"])
    def test_check_needed_repos_availability(self):
        subscription.check_needed_repos_availability(["rhel_x"])
        self.assertTrue(
            "Needed RHEL repos are available" in logger.CustomLogger.info.msg)

        subscription.check_needed_repos_availability(["rhel_z"])
        self.assertTrue("rhel_z repository is not available" in
                        logger.CustomLogger.warning.msg)

    @unit_tests.mock(logger.CustomLogger, "warning", LogMocked())
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(subscription, "get_avail_repos", lambda: [])
    def test_check_needed_repos_availability_no_repo_available(self):
        subscription.check_needed_repos_availability(["rhel"])
        self.assertTrue("rhel repository is not available" in
                        logger.CustomLogger.warning.msg)

    @unit_tests.mock(os.path, "isdir", lambda x: True)
    @unit_tests.mock(os, "listdir", lambda x: [])
    def test_replace_subscription_manager_rpms_not_available(self):
        self.assertRaises(SystemExit,
                          subscription.replace_subscription_manager)

        os.path.isdir = lambda x: False
        os.listdir = lambda x: ["filename"]
        self.assertRaises(SystemExit,
                          subscription.replace_subscription_manager)

    @unit_tests.mock(pkghandler, "get_installed_pkgs_w_different_fingerprint",
                     lambda x, y: [namedtuple('Pkg', ['name'])("submgr")])
    @unit_tests.mock(pkghandler, "print_pkg_info", lambda x: None)
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(utils, "remove_pkgs", DumbCallable())
    def test_remove_original_subscription_manager(self):
        subscription.remove_original_subscription_manager()

        self.assertEqual(utils.remove_pkgs.called, 1)

    @unit_tests.mock(os.path, "isdir", lambda x: True)
    @unit_tests.mock(os, "listdir", lambda x: ["filename"])
    @unit_tests.mock(pkghandler, "call_yum_cmd",
                     lambda a, b, enable_repos, disable_repos, set_releasever:
                     (None, 1))
    def test_install_rhel_subscription_manager_unable_to_install(self):
        self.assertRaises(SystemExit,
                          subscription.install_rhel_subscription_manager)

    class DownloadRHSMPkgsMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0

        def __call__(self, pkgs_to_download, repo_path, repo_content):
            self.called += 1
            self.pkgs_to_download = pkgs_to_download
            self.repo_path = repo_path
            self.repo_content = repo_content

    @unit_tests.mock(system_info, "version",
                     namedtuple("Version", ["major", "minor"])(6, 0))
    @unit_tests.mock(subscription, "_download_rhsm_pkgs",
                     DownloadRHSMPkgsMocked())
    @unit_tests.mock(subscription, "_get_rhsm_cert_on_centos_7",
                     DumbCallable())
    @unit_tests.mock(utils, "mkdir_p", DumbCallable())
    def test_download_rhsm_pkgs(self):
        subscription.download_rhsm_pkgs()

        self.assertEqual(subscription._download_rhsm_pkgs.called, 1)
        self.assertEqual(subscription._download_rhsm_pkgs.pkgs_to_download, [
            "subscription-manager", "subscription-manager-rhsm-certificates",
            "subscription-manager-rhsm"
        ])

        system_info.version = namedtuple("Version", ["major", "minor"])(7, 0)

        subscription.download_rhsm_pkgs()

        self.assertEqual(subscription._download_rhsm_pkgs.called, 2)
        self.assertEqual(subscription._download_rhsm_pkgs.pkgs_to_download, [
            "subscription-manager", "subscription-manager-rhsm-certificates",
            "subscription-manager-rhsm", "python-syspurpose"
        ])
        self.assertEqual(subscription._get_rhsm_cert_on_centos_7.called, 1)

        system_info.version = namedtuple("Version", ["major", "minor"])(8, 0)

        subscription.download_rhsm_pkgs()

        self.assertEqual(subscription._download_rhsm_pkgs.called, 3)
        self.assertEqual(subscription._download_rhsm_pkgs.pkgs_to_download, [
            "subscription-manager", "subscription-manager-rhsm-certificates",
            "python3-subscription-manager-rhsm",
            "dnf-plugin-subscription-manager", "python3-syspurpose"
        ])

    class StoreContentMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0
            self.filename = None
            self.content = None

        def __call__(self, filename, content):
            self.called += 1
            self.filename = filename
            self.content = content
            return True

    class DownloadPkgsMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0
            self.to_return = ["/path/to.rpm"]

        def __call__(self, pkgs, dest, reposdir=None):
            self.called += 1
            self.pkgs = pkgs
            self.dest = dest
            self.reposdir = reposdir
            return self.to_return

    @unit_tests.mock(utils, "store_content_to_file", StoreContentMocked())
    @unit_tests.mock(utils, "download_pkgs", DownloadPkgsMocked())
    def test__download_rhsm_pkgs(self):
        subscription._download_rhsm_pkgs(["testpkg"], "/path/to.repo",
                                         "content")

        self.assertTrue(
            "/path/to.repo" in utils.store_content_to_file.filename)
        self.assertEqual(utils.download_pkgs.called, 1)

        utils.download_pkgs.to_return.append(None)

        self.assertRaises(SystemExit, subscription._download_rhsm_pkgs,
                          ["testpkg"], "/path/to.repo", "content")

    class DownloadPkgMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0
            self.to_return = "/path/to.rpm"

        def __call__(self, pkg, dest, reposdir=None):
            self.called += 1
            self.pkg = pkg
            self.dest = dest
            self.reposdir = reposdir
            return self.to_return

    @unit_tests.mock(utils, "download_pkg", DownloadPkgMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    @unit_tests.mock(utils, "store_content_to_file", StoreContentMocked())
    @unit_tests.mock(utils, "mkdir_p", DumbCallable())
    def test_get_rhsm_cert_on_centos_7(self):
        # test the case of python-rhsm-certificates download failing
        utils.download_pkg.to_return = None
        self.assertRaises(SystemExit, subscription._get_rhsm_cert_on_centos_7)
        # return back some sane output
        utils.download_pkg.to_return = "/path/to.rpm"

        # test the case when getting the cpio archive out of the python-rhsm-certificates rpm is failing
        utils.run_subprocess.tuples = [("output", 1)]
        self.assertRaises(SystemExit, subscription._get_rhsm_cert_on_centos_7)

        # test the case when extracting the certificate out of the cpio archive fails
        utils.run_subprocess.tuples = [("output", 0), ("output", 1)]
        self.assertRaises(SystemExit, subscription._get_rhsm_cert_on_centos_7)
        # reset the called counter
        utils.store_content_to_file.called = 0

        # test the case when everything passes and two files are stored - the cpio archive and the extracted cert file
        subscription._get_rhsm_cert_on_centos_7()
        self.assertEqual(utils.store_content_to_file.called, 2)
Beispiel #6
0
class TestMain(unittest.TestCase):
    class AskToContinueMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return

    eula_dir = os.path.realpath(
        os.path.join(os.path.dirname(__file__), "..", "data",
                     "version-independent"))

    @unit_tests.mock(utils, "DATA_DIR", eula_dir)
    def test_show_eula(self):
        main.show_eula()

    class GetFakeFunctionMocked(unit_tests.MockFunction):
        def __call__(self, filename):
            pass

    class GetFileContentMocked(unit_tests.MockFunction):
        def __call__(self, filename):
            return utils.get_file_content_orig(unit_tests.NONEXISTING_FILE)

    class GetLoggerMocked(unit_tests.MockFunction):
        def __init__(self):
            self.info_msgs = []
            self.critical_msgs = []

        def __call__(self, msg):
            return self

        def task(self, msg):
            pass

        def critical(self, msg):
            self.critical_msgs.append(msg)
            raise SystemExit(1)

        def info(self, msg):
            pass

        def debug(self, msg):
            pass

    class CallOrderMocked(unit_tests.MockFunction):
        calls = OrderedDict()

        def __init__(self, method_name):
            self.method_name = method_name

        def __call__(self, *args):
            self.add_call(self.method_name)
            return args

        @classmethod
        def add_call(cls, method_name):
            if method_name in cls.calls:
                cls.calls[method_name] += 1
            else:
                cls.calls[method_name] = 1

        @classmethod
        def reset(cls):
            cls.calls = OrderedDict()

    class CallYumCmdMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0
            self.return_code = 0
            self.return_string = "Test output"
            self.fail_once = False
            self.command = None
            self.args = None

        def __call__(self, command, args):
            if self.fail_once and self.called == 0:
                self.return_code = 1
            if self.fail_once and self.called > 0:
                self.return_code = 0
            self.called += 1
            self.command = command
            self.args = args
            return self.return_string, self.return_code

    @unit_tests.mock(main, "loggerinst", GetLoggerMocked())
    @unit_tests.mock(utils, "get_file_content", GetFileContentMocked())
    def test_show_eula_nonexisting_file(self):
        self.assertRaises(SystemExit, main.show_eula)
        self.assertEqual(len(main.loggerinst.critical_msgs), 1)

    @unit_tests.mock(
        backup.changed_pkgs_control,
        "restore_pkgs",
        unit_tests.CountableMockObject(),
    )
    @unit_tests.mock(
        redhatrelease.system_release_file,
        "restore",
        unit_tests.CountableMockObject(),
    )
    @unit_tests.mock(
        redhatrelease.os_release_file,
        "restore",
        unit_tests.CountableMockObject(),
    )
    @unit_tests.mock(
        special_cases.shim_x64_pkg_protection_file,
        "restore",
        unit_tests.CountableMockObject(),
    )
    @unit_tests.mock(repo, "restore_yum_repos",
                     unit_tests.CountableMockObject())
    @unit_tests.mock(subscription, "rollback",
                     unit_tests.CountableMockObject())
    @unit_tests.mock(
        pkghandler.versionlock_file,
        "restore",
        unit_tests.CountableMockObject(),
    )
    @unit_tests.mock(cert.SystemCert, "_get_cert", lambda _get_cert:
                     ("anything", "anything"))
    @unit_tests.mock(cert.SystemCert, "remove",
                     unit_tests.CountableMockObject())
    def test_rollback_changes(self):
        main.rollback_changes()
        self.assertEqual(backup.changed_pkgs_control.restore_pkgs.called, 1)
        self.assertEqual(repo.restore_yum_repos.called, 1)
        self.assertEqual(redhatrelease.system_release_file.restore.called, 1)
        self.assertEqual(redhatrelease.os_release_file.restore.called, 1)
        self.assertEqual(
            special_cases.shim_x64_pkg_protection_file.restore.called, 1)
        self.assertEqual(subscription.rollback.called, 1)
        self.assertEqual(pkghandler.versionlock_file.restore.called, 1)
        self.assertEqual(cert.SystemCert.remove.called, 1)

    @unit_tests.mock(main.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(tool_opts, "no_rhsm", False)
    @unit_tests.mock(cert.SystemCert, "_get_cert", lambda _get_cert:
                     ("anything", "anything"))
    @mock_calls(main.special_cases, "check_and_resolve", CallOrderMocked)
    @mock_calls(main.checks, "perform_pre_checks", CallOrderMocked)
    @mock_calls(main.checks, "perform_pre_ponr_checks", CallOrderMocked)
    @mock_calls(pkghandler, "remove_excluded_pkgs", CallOrderMocked)
    @mock_calls(subscription, "replace_subscription_manager", CallOrderMocked)
    @mock_calls(subscription, "verify_rhsm_installed", CallOrderMocked)
    @mock_calls(pkghandler, "remove_repofile_pkgs", CallOrderMocked)
    @mock_calls(cert.SystemCert, "install", CallOrderMocked)
    @mock_calls(pkghandler, "list_third_party_pkgs", CallOrderMocked)
    @mock_calls(subscription, "subscribe_system", CallOrderMocked)
    @mock_calls(repo, "get_rhel_repoids", CallOrderMocked)
    @mock_calls(subscription, "check_needed_repos_availability",
                CallOrderMocked)
    @mock_calls(subscription, "disable_repos", CallOrderMocked)
    @mock_calls(subscription, "enable_repos", CallOrderMocked)
    @mock_calls(subscription, "download_rhsm_pkgs", CallOrderMocked)
    @unit_tests.mock(checks, "check_readonly_mounts", GetFakeFunctionMocked)
    def test_pre_ponr_conversion_order_with_rhsm(self):
        self.CallOrderMocked.reset()
        main.pre_ponr_conversion()

        intended_call_order = OrderedDict()
        intended_call_order["list_third_party_pkgs"] = 1
        intended_call_order["remove_excluded_pkgs"] = 1
        intended_call_order["check_and_resolve"] = 1
        intended_call_order["download_rhsm_pkgs"] = 1
        intended_call_order["replace_subscription_manager"] = 1
        intended_call_order["verify_rhsm_installed"] = 1
        intended_call_order["install"] = 1
        intended_call_order["subscribe_system"] = 1
        intended_call_order["get_rhel_repoids"] = 1
        intended_call_order["check_needed_repos_availability"] = 1
        intended_call_order["disable_repos"] = 1
        intended_call_order["remove_repofile_pkgs"] = 1
        intended_call_order["enable_repos"] = 1
        intended_call_order["perform_pre_ponr_checks"] = 1
        intended_call_order["perform_pre_checks"] = 1

        # Merge the two together like a zipper, creates a tuple which we can assert with - including method call order!
        zipped_call_order = zip(intended_call_order.items(),
                                self.CallOrderMocked.calls.items())
        for expected, actual in zipped_call_order:
            if expected[1] > 0:
                self.assertEqual(expected, actual)

    @unit_tests.mock(main.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(tool_opts, "no_rhsm", False)
    @unit_tests.mock(cert.SystemCert, "_get_cert", lambda _get_cert:
                     ("anything", "anything"))
    @mock_calls(main.special_cases, "check_and_resolve", CallOrderMocked)
    @mock_calls(main.checks, "perform_pre_checks", CallOrderMocked)
    @mock_calls(main.checks, "perform_pre_ponr_checks", CallOrderMocked)
    @mock_calls(pkghandler, "remove_excluded_pkgs", CallOrderMocked)
    @mock_calls(subscription, "replace_subscription_manager", CallOrderMocked)
    @mock_calls(subscription, "verify_rhsm_installed", CallOrderMocked)
    @mock_calls(pkghandler, "remove_repofile_pkgs", CallOrderMocked)
    @mock_calls(cert.SystemCert, "install", CallOrderMocked)
    @mock_calls(pkghandler, "list_third_party_pkgs", CallOrderMocked)
    @mock_calls(subscription, "subscribe_system", CallOrderMocked)
    @mock_calls(repo, "get_rhel_repoids", CallOrderMocked)
    @mock_calls(subscription, "check_needed_repos_availability",
                CallOrderMocked)
    @mock_calls(subscription, "disable_repos", CallOrderMocked)
    @mock_calls(subscription, "enable_repos", CallOrderMocked)
    @mock_calls(subscription, "download_rhsm_pkgs", CallOrderMocked)
    @unit_tests.mock(checks, "check_readonly_mounts", GetFakeFunctionMocked)
    def test_pre_ponr_conversion_order_without_rhsm(self):
        self.CallOrderMocked.reset()
        main.pre_ponr_conversion()

        intended_call_order = OrderedDict()

        intended_call_order["list_third_party_pkgs"] = 1
        intended_call_order["remove_excluded_pkgs"] = 1
        intended_call_order["check_and_resolve"] = 1

        # Do not expect this one to be called - related to RHSM
        intended_call_order["download_rhsm_pkgs"] = 0
        intended_call_order["replace_subscription_manager"] = 0
        intended_call_order["verify_rhsm_installed"] = 0
        intended_call_order["install"] = 0
        intended_call_order["subscribe_system"] = 0
        intended_call_order["get_rhel_repoids"] = 0
        intended_call_order["check_needed_repos_availability"] = 0
        intended_call_order["disable_repos"] = 0

        intended_call_order["remove_repofile_pkgs"] = 1

        intended_call_order["enable_repos"] = 0

        intended_call_order["perform_pre_ponr_checks"] = 1

        # Merge the two together like a zipper, creates a tuple which we can assert with - including method call order!
        zipped_call_order = zip(intended_call_order.items(),
                                self.CallOrderMocked.calls.items())
        for expected, actual in zipped_call_order:
            if expected[1] > 0:
                self.assertEqual(expected, actual)
class TestSubscription(unittest.TestCase):
    class GetAvailSubsMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return [namedtuple('Sub', ['pool_id', 'sub_raw'])(
                'samplepool',
                'Subscription description'
            )]

    class GetNoAvailSubsMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return []

    class GetNoAvailSubsOnceMocked(unit_tests.MockFunction):
        def __init__(self):
            self.empty_last_call = False

        def __call__(self, *args, **kwargs):
            if not self.empty_last_call:
                self.empty_last_call = True
                return []

            self.empty_last_call = False
            return [namedtuple('Sub', ['pool_id', 'sub_raw'])(
                'samplepool',
                'Subscription description'
            )]

    class LetUserChooseItemMocked(unit_tests.MockFunction):
        def __call__(self, *args, **kwargs):
            return 0

    class GetRegistrationCmdMocked(unit_tests.MockFunction):
        def __call__(self):
            return "subscription-manager register whatever-options"

    class RunSubprocessMocked(unit_tests.MockFunction):
        def __init__(self, tuples=None):
            # you can specify sequence of return (object, return code) as
            # a list of tuple that will be consumed continuosly on the each
            # call; when the list is consumed or it is empty, the default
            # tuple is returned
            self.tuples = tuples
            self.default_tuple = ('output', 0)
            self.called = 0
            self.cmd = ""

        def __call__(self, cmd, *args, **kwargs):
            self.cmd = cmd
            self.called += 1

            if self.tuples:
                return self.tuples.pop(0)
            return self.default_tuple

    class RegisterSystemMocked(unit_tests.MockFunction):
        def __init__(self):
            self.called = 0

        def __call__(self, *args, **kwargs):
            self.called += 1

    class GetLoggerMocked(unit_tests.MockFunction):
        def __init__(self):
            self.task_msgs = []
            self.info_msgs = []
            self.warning_msgs = []
            self.critical_msgs = []

        def __call__(self, msg):
            return self

        def critical(self, msg):
            self.critical_msgs.append(msg)
            raise SystemExit(1)

        def task(self, msg):
            self.task_msgs.append(msg)

        def info(self, msg):
            self.info_msgs.append(msg)

        def warn(self, msg, *args):
            self.warning_msgs.append(msg)

        def warning(self, msg, *args):
            self.warn(msg, *args)

        def debug(self, msg):
            pass

    class IsFileMocked(unit_tests.MockFunction):
        def __init__(self, is_file):
            self.is_file = is_file

        def __call__(self, *args, **kwargs):
            return self.is_file

    class PromptUserMocked(unit_tests.MockFunction):

        def __call__(self, *args, **kwargs):
            return True

    class RemoveFileMocked(unit_tests.MockFunction):
        def __init__(self, removed=True):
            self.removed = removed

        def __call__(self, *args, **kwargs):
            return self.removed

    ##########################################################################

    def setUp(self):
        tool_opts.__init__()

    def test_get_registration_cmd(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        expected = \
            'subscription-manager register --force --username=user --password="******"'
        self.assertEqual(subscription.get_registration_cmd(), expected)

    @unit_tests.mock(subscription, "get_avail_subs", GetAvailSubsMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_attach_subscription_available(self):
        self.assertEqual(subscription.attach_subscription(), True)

    @unit_tests.mock(subscription, "get_avail_subs", GetAvailSubsMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    @unit_tests.mock(tool_opts, "activation_key", "dummy_activate_key")
    def test_attach_subscription_available_with_activation_key(self):
        self.assertEqual(subscription.attach_subscription(), True)

    @unit_tests.mock(subscription, "get_avail_subs", GetNoAvailSubsMocked())
    def test_attach_subscription_none_available(self):
        self.assertEqual(subscription.attach_subscription(), False)

    @unit_tests.mock(subscription, "register_system", RegisterSystemMocked())
    @unit_tests.mock(subscription, "get_avail_subs", GetAvailSubsMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_subscribe_system(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        subscription.subscribe_system()
        self.assertEqual(subscription.register_system.called, 1)

    @unit_tests.mock(subscription, "register_system", RegisterSystemMocked())
    @unit_tests.mock(subscription, "get_avail_subs", GetNoAvailSubsOnceMocked())
    @unit_tests.mock(utils, "let_user_choose_item", LetUserChooseItemMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_subscribe_system_fail_once(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        subscription.subscribe_system()
        self.assertEqual(subscription.register_system.called, 2)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked([("nope", 1)]))
    def test_register_system_fail_non_interactive(self):
        # Check the critical severity is logged when the credentials are given
        # on the cmdline but registration fails
        tool_opts.username = '******'
        tool_opts.password = '******'
        tool_opts.credentials_thru_cli = True
        self.assertRaises(SystemExit, subscription.register_system)
        self.assertEqual(len(subscription.logging.getLogger.critical_msgs), 1)

    @unit_tests.mock(utils,
                     "run_subprocess",
                     RunSubprocessMocked(tuples=[("nope", 1), ("nope", 2), ("Success", 0)]))
    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(subscription, "get_registration_cmd", GetRegistrationCmdMocked())
    def test_register_system_fail_interactive(self):
        # Check the function tries to register multiple times without
        # critical log.
        tool_opts.credentials_thru_cli = False
        subscription.register_system()
        self.assertEqual(utils.run_subprocess.called, 3)
        self.assertEqual(len(subscription.logging.getLogger.critical_msgs), 0)

    def test_hiding_password(self):
        test_cmd = 'subscription-manager register --force ' \
                   '--username=jdoe --password="******" --org=0123'
        pswds_to_test = [
            "my favourite password",
            "\\)(*&^%f %##@^%&*&^(",
            " ",
            ""
        ]
        for pswd in pswds_to_test:
            sanitized_cmd = subscription.hide_password(test_cmd % pswd)
            self.assertEqual(
                sanitized_cmd,
                'subscription-manager register --force '
                '--username=jdoe --password="******" --org=0123')

    def test_rhsm_serverurl(self):
        tool_opts.username = '******'
        tool_opts.password = '******'
        tool_opts.serverurl = 'url'
        expected = \
            'subscription-manager register --force --username=user --password="******" --serverurl="url"'
        self.assertEqual(subscription.get_registration_cmd(), expected)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    def test_get_pool_id(self):
        # Check that we can distill the pool id from the subscription description
        pool_id = subscription.get_pool_id(self.SUBSCRIPTION_DETAILS)

        self.assertEqual(pool_id, "8aaaa123045897fb564240aa00aa0000")

    # Details of one subscription as output by `subscription-manager list --available`
    SUBSCRIPTION_DETAILS = (
        "Subscription Name: Good subscription\n"
        "Provides:          Something good\n"
        "SKU:               00EEE00EE\n"
        "Contract:          01234567\n"
        "Pool ID:           8aaaa123045897fb564240aa00aa0000\n"
        "Available:         1\n"
        "Suggested:         1\n"
        "Service Level:     Self-icko\n"
        "Service Type:      L1-L3\n"
        "Subscription Type: Standard\n"
        "Ends:              2018/26/07\n"
        "System Type:       Virtual\n\n"  # this has changed to Entitlement Type since RHEL 7.8
    )

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
    def test_unregister_system_successfully(self):
        unregistration_cmd = "subscription-manager unregister"
        subscription.unregister_system()
        self.assertEqual(utils.run_subprocess.called, 1)
        self.assertEqual(utils.run_subprocess.cmd, unregistration_cmd)
        self.assertEqual(len(subscription.logging.getLogger.info_msgs), 1)
        self.assertEqual(len(subscription.logging.getLogger.task_msgs), 1)
        self.assertEqual(len(subscription.logging.getLogger.warning_msgs), 0)

    @unit_tests.mock(subscription.logging, "getLogger", GetLoggerMocked())
    @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked([('output', 1)]))
    def test_unregister_system_fails(self):
        unregistration_cmd = "subscription-manager unregister"
        subscription.unregister_system()
        self.assertEqual(utils.run_subprocess.called, 1)
        self.assertEqual(utils.run_subprocess.cmd, unregistration_cmd)
        self.assertEqual(len(subscription.logging.getLogger.info_msgs), 0)
        self.assertEqual(len(subscription.logging.getLogger.task_msgs), 1)
        self.assertEqual(len(subscription.logging.getLogger.warning_msgs), 1)

    @unit_tests.mock(subscription, "rollback_renamed_repo_files", unit_tests.CountableMockObject())
    @unit_tests.mock(subscription, "unregister_system", unit_tests.CountableMockObject())
    def test_rollback(self):
        subscription.rollback()
        self.assertEqual(subscription.rollback_renamed_repo_files.called, 1)
        self.assertEqual(subscription.unregister_system.called, 1)

    class LogMocked(unit_tests.MockFunction):
        def __init__(self):
            self.msg = ""

        def __call__(self, msg):
            self.msg += "%s\n" % msg

    @unit_tests.mock(logger.CustomLogger, "info", LogMocked())
    @unit_tests.mock(logger.CustomLogger, "warning", LogMocked())
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(subscription, "get_avail_repos", lambda: ["rhel_x", "rhel_y"])
    def test_check_needed_repos_availability(self):
        subscription.check_needed_repos_availability(["rhel_x"])
        self.assertTrue("Needed RHEL repos are available" in logger.CustomLogger.info.msg)

        subscription.check_needed_repos_availability(["rhel_z"])
        self.assertTrue("rhel_z repository is not available" in logger.CustomLogger.warning.msg)

    @unit_tests.mock(logger.CustomLogger, "warning", LogMocked())
    @unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
    @unit_tests.mock(subscription, "get_avail_repos", lambda: [])
    def test_check_needed_repos_availability_no_repo_available(self):
        subscription.check_needed_repos_availability(["rhel"])
        self.assertTrue("rhel repository is not available" in logger.CustomLogger.warning.msg)