def test_invalid_service_names(self, _m_request_updated_contract, m_getuid, service, beta, FakeConfig): m_getuid.return_value = 0 expected_error_tmpl = status.MESSAGE_INVALID_SERVICE_OP_FAILURE_TMPL expected_msg = "One moment, checking your subscription first\n" cfg = FakeConfig.for_attached_machine() with pytest.raises(exceptions.UserFacingError) as err: fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): args = mock.MagicMock() args.service = service args.beta = beta action_enable(args, cfg) assert expected_msg == fake_stdout.getvalue() if beta: ent_str = "Try " + entitlements.ALL_ENTITLEMENTS_STR else: ent_str = "Try " + entitlements.RELEASED_ENTITLEMENTS_STR service_msg = "\n".join( textwrap.wrap(ent_str, width=80, break_long_words=False)) assert (expected_error_tmpl.format( operation="enable", name=", ".join(sorted(service)), service_msg=service_msg, ) == err.value.msg)
def test_invalid_service_error_message( self, _request_updated_contract, m_getuid, uid, expected_error_template, FakeConfig, ): """Check invalid service name results in custom error message.""" m_getuid.return_value = uid cfg = FakeConfig.for_attached_machine() with pytest.raises(exceptions.UserFacingError) as err: args = mock.MagicMock() args.service = ["bogus"] action_enable(args, cfg) service_msg = "\n".join( textwrap.wrap( "Try " + entitlements.ALL_ENTITLEMENTS_STR, width=80, break_long_words=False, )) assert (expected_error_template.format( operation="enable", name="bogus", service_msg=service_msg) == err.value.msg)
def test_non_root_users_are_rejected(self, getuid, FakeConfig): """Check that a UID != 0 will receive a message and exit non-zero""" getuid.return_value = 1 cfg = FakeConfig.for_attached_machine() with pytest.raises(exceptions.NonRootUserError): action_enable(mock.MagicMock(), cfg)
def test_assume_yes_passed_to_service_init( self, m_entitlements, _m_get_available_resources, m_request_updated_contract, m_getuid, assume_yes, beta_flag, beta_count, FakeConfig, ): """assume-yes parameter is passed to entitlement instantiation.""" m_getuid.return_value = 0 m_entitlement_cls = mock.MagicMock() m_ent_is_beta = mock.PropertyMock(return_value=False) type(m_entitlement_cls).is_beta = m_ent_is_beta m_entitlements.ENTITLEMENT_CLASS_BY_NAME = { "testitlement": m_entitlement_cls } m_entitlement_obj = m_entitlement_cls.return_value m_entitlement_obj.enable.return_value = True cfg = FakeConfig.for_attached_machine() args = mock.MagicMock() args.service = ["testitlement"] args.assume_yes = assume_yes args.beta = beta_flag action_enable(args, cfg) assert [mock.call(cfg, assume_yes=assume_yes) ] == m_entitlement_cls.call_args_list assert beta_count == m_ent_is_beta.call_count
def test_assume_yes_passed_to_service_init( self, m_entitlements, m_request_updated_contract, _m_get_available_resources, m_getuid, assume_yes, FakeConfig, ): """assume-yes parameter is passed to entitlement instantiation.""" m_getuid.return_value = 0 m_entitlement_cls = mock.Mock() m_entitlements.ENTITLEMENT_CLASS_BY_NAME = { "testitlement": m_entitlement_cls } cfg = FakeConfig.for_attached_machine() args = mock.MagicMock() args.name = "testitlement" args.assume_yes = assume_yes action_enable(args, cfg) assert [ mock.call(cfg, assume_yes=assume_yes) ] == m_entitlement_cls.call_args_list
def test_unattached_invalid_and_valid_service_error_message( self, _request_updated_contract, m_getuid, uid, expected_error_template, event, FakeConfig, ): """Check invalid service name results in custom error message.""" m_getuid.return_value = uid cfg = FakeConfig() args = mock.MagicMock() args.service = ["bogus", "fips"] args.command = "enable" with pytest.raises(exceptions.UserFacingError) as err: action_enable(args, cfg) if not uid: expected_error = expected_error_template.format( operation="enable", valid_service="fips", invalid_service="bogus", service_msg="", ) else: expected_error = expected_error_template assert expected_error.msg == err.value.msg with pytest.raises(SystemExit): with mock.patch.object( event, "_event_logger_mode", event_logger.EventLoggerMode.JSON ): fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): main_error_handler(action_enable)(args, cfg) expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "failure", "errors": [ { "message": expected_error.msg, "message_code": expected_error.name, "service": None, "type": "system", } ], "failed_services": [], "needs_reboot": False, "processed_services": [], "warnings": [], } assert expected == json.loads(fake_stdout.getvalue())
def test_lock_file_exists(self, m_subp, _request_updated_contract, getuid, FakeConfig): """Check inability to enable if operation holds lock file.""" getuid.return_value = 0 cfg = FakeConfig.for_attached_machine() cfg.write_cache("lock", "123:ua disable") with pytest.raises(exceptions.LockHeldError) as err: action_enable(mock.MagicMock(), cfg) assert [mock.call(["ps", "123"])] == m_subp.call_args_list assert ("Unable to perform: ua enable.\n" "Operation in progress: ua disable (pid:123)") == err.value.msg
def test_lock_file_exists( self, m_subp, _request_updated_contract, getuid, capsys, event, FakeConfig, ): """Check inability to enable if operation holds lock file.""" getuid.return_value = 0 cfg = FakeConfig.for_attached_machine() cfg.write_cache("lock", "123:ua disable") args = mock.MagicMock() with pytest.raises(exceptions.LockHeldError) as err: action_enable(args, cfg=cfg) assert [mock.call(["ps", "123"])] == m_subp.call_args_list expected_message = messages.LOCK_HELD_ERROR.format( lock_request="ua enable", lock_holder="ua disable", pid="123" ) assert expected_message.msg == err.value.msg with pytest.raises(SystemExit): with mock.patch.object( event, "_event_logger_mode", event_logger.EventLoggerMode.JSON ): with mock.patch.object( cfg, "check_lock_info" ) as m_check_lock_info: m_check_lock_info.return_value = (1, "lock_holder") main_error_handler(action_enable)(args, cfg) expected_msg = messages.LOCK_HELD_ERROR.format( lock_request="ua enable", lock_holder="lock_holder", pid=1 ) expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "failure", "errors": [ { "message": expected_msg.msg, "message_code": expected_msg.name, "service": None, "type": "system", } ], "failed_services": [], "needs_reboot": False, "processed_services": [], "warnings": [], } assert expected == json.loads(capsys.readouterr()[0])
def test_unattached_error_message( self, _request_updated_contract, m_getuid, uid, expected_error_template, capsys, event, FakeConfig, ): """Check that root user gets unattached message.""" m_getuid.return_value = uid cfg = FakeConfig() args = mock.MagicMock() args.command = "enable" args.service = ["esm-infra"] if not uid: expected_error = expected_error_template.format( valid_service="esm-infra" ) else: expected_error = expected_error_template with pytest.raises(exceptions.UserFacingError) as err: action_enable(args, cfg) assert expected_error.msg == err.value.msg with pytest.raises(SystemExit): with mock.patch.object( event, "_event_logger_mode", event_logger.EventLoggerMode.JSON ): main_error_handler(action_enable)(args, cfg) expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "failure", "errors": [ { "message": expected_error.msg, "message_code": expected_error.name, "service": None, "type": "system", } ], "failed_services": [], "needs_reboot": False, "processed_services": [], "warnings": [], } assert expected == json.loads(capsys.readouterr()[0])
def test_unattached_error_message(self, m_getuid, uid, expected_error_template, FakeConfig): """Check that root user gets unattached message.""" m_getuid.return_value = uid cfg = FakeConfig() with pytest.raises(exceptions.UserFacingError) as err: args = mock.MagicMock() args.name = "esm-infra" action_enable(args, cfg) assert (expected_error_template.format( name="esm-infra") == err.value.msg)
def test_invalid_service_error_message(self, m_getuid, uid, expected_error_template): """Check invalid service name results in custom error message.""" m_getuid.return_value = uid cfg = FakeConfig.for_attached_machine() with pytest.raises(exceptions.UserFacingError) as err: args = mock.MagicMock() args.name = "bogus" action_enable(args, cfg) assert (expected_error_template.format(operation="enable", name="bogus") == err.value.msg)
def test_non_root_users_are_rejected( self, _m_resources, _request_updated_contract, getuid, capsys, event, FakeConfig, ): """Check that a UID != 0 will receive a message and exit non-zero""" getuid.return_value = 1 args = mock.MagicMock() cfg = FakeConfig.for_attached_machine() with pytest.raises(exceptions.NonRootUserError): action_enable(args, cfg=cfg) with pytest.raises(SystemExit): with mock.patch( "sys.argv", [ "/usr/bin/ua", "enable", "foobar", "--assume-yes", "--format", "json", ], ): main() expected_message = messages.NONROOT_USER expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "failure", "errors": [ { "message": expected_message.msg, "message_code": expected_message.name, "service": None, "type": "system", } ], "failed_services": [], "needs_reboot": False, "processed_services": [], "warnings": [], } assert expected == json.loads(capsys.readouterr()[0])
def _prompt_for_enable(cfg: UAConfig, service: str) -> bool: """Prompt for enable a ua service. :return: True if enable performed. """ import argparse from uaclient import cli print(messages.SECURITY_SERVICE_DISABLED.format(service=service)) choice = util.prompt_choices( "Choose: [E]nable {} [C]ancel".format(service), valid_choices=["e", "c"], ) if choice == "e": print(colorize_commands([["ua", "enable", service]])) return bool( 0 == cli.action_enable( argparse.Namespace( service=[service], assume_yes=True, beta=False, format="cli", ), cfg, ) ) return False
def test_invalid_service_names(self, m_getuid, names, FakeConfig): m_getuid.return_value = 0 expected_error_tmpl = status.MESSAGE_INVALID_SERVICE_OP_FAILURE_TMPL expected_msg = "One moment, checking your subscription first\n" cfg = FakeConfig.for_attached_machine() with pytest.raises(exceptions.UserFacingError) as err: fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): args = mock.MagicMock() args.names = names action_enable(args, cfg) assert expected_msg == fake_stdout.getvalue() assert (expected_error_tmpl.format( operation="enable", name=", ".join(sorted(names))) == err.value.msg)
def test_assume_yes_passed_to_service_init( self, m_valid_services, _m_get_available_resources, m_request_updated_contract, m_getuid, assume_yes, FakeConfig, ): """assume-yes parameter is passed to entitlement instantiation.""" m_getuid.return_value = 0 m_entitlement_cls = mock.MagicMock() m_valid_services.return_value = ["testitlement"] m_entitlement_obj = m_entitlement_cls.return_value m_entitlement_obj.enable.return_value = (True, None) cfg = FakeConfig.for_attached_machine() args = mock.MagicMock() args.service = ["testitlement"] args.assume_yes = assume_yes args.beta = False with mock.patch( "uaclient.entitlements.entitlement_factory", return_value=m_entitlement_cls, ): action_enable(args, cfg) assert [ mock.call( cfg, assume_yes=assume_yes, allow_beta=False, called_name="testitlement", ) ] == m_entitlement_cls.call_args_list
def test_entitlements_not_found_disabled_and_enabled( self, m_entitlements, _m_get_available_resources, m_getuid, silent_if_inapplicable, beta_flag, beta_count, FakeConfig, ): m_getuid.return_value = 0 expected_error_tmpl = status.MESSAGE_INVALID_SERVICE_OP_FAILURE_TMPL m_ent1_cls = mock.Mock() m_ent1_obj = m_ent1_cls.return_value m_ent1_obj.enable.return_value = False m_ent2_cls = mock.Mock() m_ent2_is_beta = mock.PropertyMock(return_value=False) type(m_ent2_cls).is_beta = m_ent2_is_beta m_ent2_obj = m_ent2_cls.return_value m_ent2_obj.enable.return_value = False m_ent3_cls = mock.Mock() m_ent3_is_beta = mock.PropertyMock(return_value=False) type(m_ent3_cls).is_beta = m_ent3_is_beta m_ent3_obj = m_ent3_cls.return_value m_ent3_obj.enable.return_value = True m_entitlements.ENTITLEMENT_CLASS_BY_NAME = { "ent2": m_ent2_cls, "ent3": m_ent3_cls, } cfg = FakeConfig.for_attached_machine() assume_yes = False args_mock = mock.Mock() args_mock.names = ["ent1", "ent2", "ent3"] args_mock.assume_yes = assume_yes args_mock.beta = beta_flag expected_msg = "One moment, checking your subscription first\n" with pytest.raises(exceptions.UserFacingError) as err: fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): action_enable(args_mock, cfg) assert (expected_error_tmpl.format(operation="enable", name="ent1") == err.value.msg) assert expected_msg == fake_stdout.getvalue() for m_ent_cls in [m_ent2_cls, m_ent3_cls]: assert [mock.call(cfg, assume_yes=assume_yes) ] == m_ent_cls.call_args_list expected_enable_call = mock.call(silent_if_inapplicable=False) for m_ent in [m_ent2_obj, m_ent3_obj]: assert [expected_enable_call] == m_ent.enable.call_args_list assert 0 == m_ent1_obj.call_count assert beta_count == m_ent2_is_beta.call_count assert beta_count == m_ent3_is_beta.call_count
def test_invalid_service_error_message( self, _request_updated_contract, m_getuid, uid, expected_error_template, is_attached, event, FakeConfig, ): """Check invalid service name results in custom error message.""" m_getuid.return_value = uid if is_attached: cfg = FakeConfig.for_attached_machine() service_msg = "\n".join( textwrap.wrap( ( "Try " + ", ".join( entitlements.valid_services( cfg=cfg, allow_beta=True ) ) + "." ), width=80, break_long_words=False, break_on_hyphens=False, ) ) else: cfg = FakeConfig() service_msg = "See https://ubuntu.com/advantage" args = mock.MagicMock() args.service = ["bogus"] args.command = "enable" with pytest.raises(exceptions.UserFacingError) as err: action_enable(args, cfg) if not uid: expected_error = expected_error_template.format( operation="enable", invalid_service="bogus", service_msg=service_msg, ) else: expected_error = expected_error_template assert expected_error.msg == err.value.msg with pytest.raises(SystemExit): with mock.patch.object( event, "_event_logger_mode", event_logger.EventLoggerMode.JSON ): fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): main_error_handler(action_enable)(args, cfg) expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "failure", "errors": [ { "message": expected_error.msg, "message_code": expected_error.name, "service": None, "type": "system", } ], "failed_services": ["bogus"] if not uid and is_attached else [], "needs_reboot": False, "processed_services": [], "warnings": [], } assert expected == json.loads(fake_stdout.getvalue())
def test_entitlements_not_found_and_beta( self, m_entitlements, _m_get_available_resources, _m_request_updated_contract, m_getuid, silent_if_inapplicable, beta_flag, beta_count, FakeConfig, ): m_getuid.return_value = 0 expected_error_tmpl = status.MESSAGE_INVALID_SERVICE_OP_FAILURE_TMPL m_ent1_cls = mock.Mock() m_ent1_obj = m_ent1_cls.return_value m_ent1_obj.enable.return_value = False m_ent2_cls = mock.Mock() m_ent2_is_beta = mock.PropertyMock(return_value=True) type(m_ent2_cls).is_beta = m_ent2_is_beta m_ent2_obj = m_ent2_cls.return_value m_ent2_obj.enable.return_value = False m_ent3_cls = mock.Mock() m_ent3_is_beta = mock.PropertyMock(return_value=False) type(m_ent3_cls).is_beta = m_ent3_is_beta m_ent3_obj = m_ent3_cls.return_value m_ent3_obj.enable.return_value = True m_entitlements.ENTITLEMENT_CLASS_BY_NAME = { "ent2": m_ent2_cls, "ent3": m_ent3_cls, } cfg = FakeConfig.for_attached_machine() assume_yes = False args_mock = mock.Mock() args_mock.service = ["ent1", "ent2", "ent3"] args_mock.assume_yes = assume_yes args_mock.beta = beta_flag expected_msg = "One moment, checking your subscription first\n" m_entitlements.RELEASED_ENTITLEMENTS_STR = "ent1, ent3" m_entitlements.ALL_ENTITLEMENTS_STR = "ent1, ent2, ent3" not_found_name = "ent1" mock_ent_list = [m_ent3_cls] mock_obj_list = [m_ent3_obj] if not beta_flag: not_found_name += ", ent2" ent_str = "Try " + m_entitlements.RELEASED_ENTITLEMENTS_STR else: ent_str = "Try " + m_entitlements.ALL_ENTITLEMENTS_STR mock_ent_list.append(m_ent2_cls) mock_obj_list.append(m_ent3_obj) service_msg = "\n".join( textwrap.wrap(ent_str, width=80, break_long_words=False)) with pytest.raises(exceptions.UserFacingError) as err: fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): action_enable(args_mock, cfg) assert (expected_error_tmpl.format( operation="enable", name=not_found_name, service_msg=service_msg, ) == err.value.msg) assert expected_msg == fake_stdout.getvalue() for m_ent_cls in mock_ent_list: assert [mock.call(cfg, assume_yes=assume_yes) ] == m_ent_cls.call_args_list expected_enable_call = mock.call(silent_if_inapplicable=False) for m_ent in mock_obj_list: assert [expected_enable_call] == m_ent.enable.call_args_list assert 0 == m_ent1_obj.call_count assert beta_count == m_ent2_is_beta.call_count assert beta_count == m_ent3_is_beta.call_count
def test_entitlement_instantiated_and_enabled( self, m_status, _m_get_available_resources, _m_request_updated_contract, m_getuid, allow_beta, event, FakeConfig, ): m_getuid.return_value = 0 m_entitlement_cls = mock.Mock() m_entitlement_obj = m_entitlement_cls.return_value m_entitlement_obj.enable.return_value = (True, None) cfg = FakeConfig.for_attached_machine() args_mock = mock.MagicMock() args_mock.assume_yes = False args_mock.beta = allow_beta args_mock.service = ["testitlement"] with mock.patch( "uaclient.entitlements.entitlement_factory", return_value=m_entitlement_cls, ), mock.patch( "uaclient.entitlements.valid_services", return_value=["testitlement"], ): ret = action_enable(args_mock, cfg) assert [ mock.call( cfg, assume_yes=False, allow_beta=allow_beta, called_name="testitlement", ) ] == m_entitlement_cls.call_args_list m_entitlement = m_entitlement_cls.return_value expected_enable_call = mock.call() expected_ret = 0 assert [expected_enable_call] == m_entitlement.enable.call_args_list assert expected_ret == ret assert 1 == m_status.call_count with mock.patch( "uaclient.entitlements.entitlement_factory", return_value=m_entitlement_cls, ), mock.patch( "uaclient.entitlements.valid_services", return_value=["testitlement"], ), mock.patch.object( event, "_event_logger_mode", event_logger.EventLoggerMode.JSON ): fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): ret = action_enable(args_mock, cfg=cfg) expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "success", "errors": [], "failed_services": [], "needs_reboot": False, "processed_services": ["testitlement"], "warnings": [], } assert expected == json.loads(fake_stdout.getvalue()) assert expected_ret == ret
def test_invalid_service_names( self, _m_request_updated_contract, m_getuid, service, beta, event, FakeConfig, ): m_getuid.return_value = 0 expected_error_tmpl = messages.INVALID_SERVICE_OP_FAILURE expected_msg = "One moment, checking your subscription first\n" cfg = FakeConfig.for_attached_machine() args_mock = mock.MagicMock() args_mock.service = service args_mock.beta = beta with pytest.raises(exceptions.UserFacingError) as err: fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): action_enable(args_mock, cfg) assert expected_msg == fake_stdout.getvalue() service_names = entitlements.valid_services(cfg=cfg, allow_beta=beta) ent_str = "Try " + ", ".join(service_names) + "." service_msg = "\n".join( textwrap.wrap( ent_str, width=80, break_long_words=False, break_on_hyphens=False, ) ) expected_error = expected_error_tmpl.format( operation="enable", invalid_service=", ".join(sorted(service)), service_msg=service_msg, ) assert expected_error.msg == err.value.msg with pytest.raises(SystemExit): with mock.patch.object( event, "_event_logger_mode", event_logger.EventLoggerMode.JSON ): fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): main_error_handler(action_enable)(args_mock, cfg) expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "failure", "errors": [ { "message": expected_error.msg, "message_code": expected_error.name, "service": None, "type": "system", } ], "failed_services": service, "needs_reboot": False, "processed_services": [], "warnings": [], } assert expected == json.loads(fake_stdout.getvalue())
def test_print_message_when_can_enable_fails( self, _m_get_available_resources, _m_request_updated_contract, m_getuid, event, FakeConfig, ): m_getuid.return_value = 0 m_entitlement_cls = mock.Mock() type(m_entitlement_cls).is_beta = mock.PropertyMock(return_value=False) m_entitlement_obj = m_entitlement_cls.return_value m_entitlement_obj.enable.return_value = ( False, CanEnableFailure( CanEnableFailureReason.ALREADY_ENABLED, message=messages.NamedMessage("test-code", "msg"), ), ) cfg = FakeConfig.for_attached_machine() args_mock = mock.Mock() args_mock.service = ["ent1"] args_mock.assume_yes = False args_mock.beta = False with mock.patch( "uaclient.entitlements.entitlement_factory", return_value=m_entitlement_cls, ), mock.patch( "uaclient.entitlements.valid_services", return_value=["ent1"] ): fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): action_enable(args_mock, cfg) assert ( "One moment, checking your subscription first\nmsg\n" == fake_stdout.getvalue() ) with mock.patch( "uaclient.entitlements.entitlement_factory", return_value=m_entitlement_cls, ), mock.patch( "uaclient.entitlements.valid_services", return_value=["ent1"] ), mock.patch.object( event, "_event_logger_mode", event_logger.EventLoggerMode.JSON ): fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): ret = action_enable(args_mock, cfg=cfg) expected_ret = 1 expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "failure", "errors": [ { "message": "msg", "message_code": "test-code", "service": "ent1", "type": "service", } ], "failed_services": ["ent1"], "needs_reboot": False, "processed_services": [], "warnings": [], } assert expected == json.loads(fake_stdout.getvalue()) assert expected_ret == ret
def test_entitlements_not_found_and_beta( self, m_valid_services, m_entitlement_factory, _m_get_available_resources, _m_request_updated_contract, m_getuid, beta_flag, event, FakeConfig, ): m_getuid.return_value = 0 expected_error_tmpl = messages.INVALID_SERVICE_OP_FAILURE m_ent1_cls = mock.Mock() m_ent1_obj = m_ent1_cls.return_value m_ent1_obj.enable.return_value = (False, None) m_ent2_cls = mock.Mock() m_ent2_cls.name = "ent2" m_ent2_is_beta = mock.PropertyMock(return_value=True) type(m_ent2_cls)._is_beta = m_ent2_is_beta m_ent2_obj = m_ent2_cls.return_value failure_reason = CanEnableFailure(CanEnableFailureReason.IS_BETA) if beta_flag: m_ent2_obj.enable.return_value = (True, None) else: m_ent2_obj.enable.return_value = (False, failure_reason) m_ent3_cls = mock.Mock() m_ent3_cls.name = "ent3" m_ent3_is_beta = mock.PropertyMock(return_value=False) type(m_ent3_cls)._is_beta = m_ent3_is_beta m_ent3_obj = m_ent3_cls.return_value m_ent3_obj.enable.return_value = (True, None) cfg = FakeConfig.for_attached_machine() assume_yes = False args_mock = mock.Mock() args_mock.service = ["ent1", "ent2", "ent3"] args_mock.assume_yes = assume_yes args_mock.beta = beta_flag def factory_side_effect(cfg, name, not_found_okay=True): if name == "ent2": return m_ent2_cls if name == "ent3": return m_ent3_cls return None m_entitlement_factory.side_effect = factory_side_effect def valid_services_side_effect(cfg, allow_beta, all_names=False): if allow_beta: return ["ent2", "ent3"] return ["ent2"] m_valid_services.side_effect = valid_services_side_effect expected_msg = "One moment, checking your subscription first\n" not_found_name = "ent1" mock_ent_list = [m_ent3_cls] mock_obj_list = [m_ent3_obj] service_names = entitlements.valid_services(cfg, allow_beta=beta_flag) ent_str = "Try " + ", ".join(service_names) + "." if not beta_flag: not_found_name += ", ent2" else: mock_ent_list.append(m_ent2_cls) mock_obj_list.append(m_ent3_obj) service_msg = "\n".join( textwrap.wrap( ent_str, width=80, break_long_words=False, break_on_hyphens=False, ) ) with pytest.raises(exceptions.UserFacingError) as err: fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): action_enable(args_mock, cfg) expected_error = expected_error_tmpl.format( operation="enable", invalid_service=not_found_name, service_msg=service_msg, ) assert expected_error.msg == err.value.msg assert expected_msg == fake_stdout.getvalue() for m_ent_cls in mock_ent_list: assert [ mock.call( cfg, assume_yes=assume_yes, allow_beta=beta_flag, called_name=m_ent_cls.name, ) ] == m_ent_cls.call_args_list expected_enable_call = mock.call() for m_ent in mock_obj_list: assert [expected_enable_call] == m_ent.enable.call_args_list assert 0 == m_ent1_obj.call_count event.reset() with pytest.raises(SystemExit): with mock.patch.object( event, "_event_logger_mode", event_logger.EventLoggerMode.JSON ): fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): main_error_handler(action_enable)(args_mock, cfg=cfg) expected_failed_services = ["ent1", "ent2"] if beta_flag: expected_failed_services = ["ent1"] expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "failure", "errors": [ { "message": expected_error.msg, "message_code": expected_error.name, "service": None, "type": "system", } ], "failed_services": expected_failed_services, "needs_reboot": False, "processed_services": ["ent2", "ent3"] if beta_flag else ["ent3"], "warnings": [], } assert expected == json.loads(fake_stdout.getvalue())
def test_entitlements_not_found_disabled_and_enabled( self, m_valid_services, m_entitlement_factory, _m_get_available_resources, _m_request_updated_contract, m_getuid, event, FakeConfig, ): m_getuid.return_value = 0 expected_error_tmpl = messages.INVALID_SERVICE_OP_FAILURE m_ent1_cls = mock.Mock() m_ent1_obj = m_ent1_cls.return_value m_ent1_obj.enable.return_value = (False, None) m_ent2_cls = mock.Mock() m_ent2_cls.name = "ent2" m_ent2_is_beta = mock.PropertyMock(return_value=True) type(m_ent2_cls).is_beta = m_ent2_is_beta m_ent2_obj = m_ent2_cls.return_value m_ent2_obj.enable.return_value = ( False, CanEnableFailure(CanEnableFailureReason.IS_BETA), ) m_ent3_cls = mock.Mock() m_ent3_cls.name = "ent3" m_ent3_is_beta = mock.PropertyMock(return_value=False) type(m_ent3_cls).is_beta = m_ent3_is_beta m_ent3_obj = m_ent3_cls.return_value m_ent3_obj.enable.return_value = (True, None) def factory_side_effect(cfg, name, not_found_okay=True): if name == "ent2": return m_ent2_cls if name == "ent3": return m_ent3_cls return None m_entitlement_factory.side_effect = factory_side_effect m_valid_services.return_value = ["ent2", "ent3"] cfg = FakeConfig.for_attached_machine() assume_yes = False args_mock = mock.Mock() args_mock.service = ["ent1", "ent2", "ent3"] args_mock.assume_yes = assume_yes args_mock.beta = False expected_msg = "One moment, checking your subscription first\n" with pytest.raises(exceptions.UserFacingError) as err: fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): action_enable(args_mock, cfg) expected_error = expected_error_tmpl.format( operation="enable", invalid_service="ent1, ent2", service_msg=( "Try " + ", ".join(entitlements.valid_services(allow_beta=False)) + "." ), ) assert expected_error.msg == err.value.msg assert expected_msg == fake_stdout.getvalue() for m_ent_cls in [m_ent2_cls, m_ent3_cls]: assert [ mock.call( cfg, assume_yes=assume_yes, allow_beta=False, called_name=m_ent_cls.name, ) ] == m_ent_cls.call_args_list expected_enable_call = mock.call() for m_ent in [m_ent2_obj, m_ent3_obj]: assert [expected_enable_call] == m_ent.enable.call_args_list assert 0 == m_ent1_obj.call_count event.reset() with pytest.raises(SystemExit): with mock.patch.object( event, "_event_logger_mode", event_logger.EventLoggerMode.JSON ): fake_stdout = io.StringIO() with contextlib.redirect_stdout(fake_stdout): main_error_handler(action_enable)(args_mock, cfg) expected = { "_schema_version": event_logger.JSON_SCHEMA_VERSION, "result": "failure", "errors": [ { "message": expected_error.msg, "message_code": expected_error.name, "service": None, "type": "system", } ], "failed_services": ["ent1", "ent2"], "needs_reboot": False, "processed_services": ["ent3"], "warnings": [], } assert expected == json.loads(fake_stdout.getvalue())