# This file is part of cloud-init. See LICENSE file for license information. """Tests for registering RHEL subscription via rh_subscription.""" import copy import logging from cloudinit.config import cc_rh_subscription from cloudinit import subp from cloudinit.tests.helpers import CiTestCase, mock SUBMGR = cc_rh_subscription.SubscriptionManager SUB_MAN_CLI = 'cloudinit.config.cc_rh_subscription._sub_man_cli' @mock.patch(SUB_MAN_CLI) class GoodTests(CiTestCase): with_logs = True def setUp(self): super(GoodTests, self).setUp() self.name = "cc_rh_subscription" self.cloud_init = None self.log = logging.getLogger("good_tests") self.args = [] self.handle = cc_rh_subscription.handle self.config = {'rh_subscription': {'username': 'scooby@do.com', 'password': 'scooby-snacks' }} self.config_full = {'rh_subscription': {'username': 'scooby@do.com', 'password': 'scooby-snacks', 'auto-attach': True, 'service-level': 'self-support', 'add-pool': ['pool1', 'pool2', 'pool3'], 'enable-repo': ['repo1', 'repo2', 'repo3'], 'disable-repo': ['repo4', 'repo5'] }} def test_already_registered(self, m_sman_cli): ''' Emulates a system that is already registered. Ensure it gets a non-ProcessExecution error from is_registered() ''' self.handle(self.name, self.config, self.cloud_init, self.log, self.args) self.assertEqual(m_sman_cli.call_count, 1) self.assertIn('System is already registered', self.logs.getvalue()) def test_simple_registration(self, m_sman_cli): ''' Simple registration with username and password ''' reg = "The system has been registered with ID:" \ " 12345678-abde-abcde-1234-1234567890abc" m_sman_cli.side_effect = [subp.ProcessExecutionError, (reg, 'bar')] self.handle(self.name, self.config, self.cloud_init, self.log, self.args) self.assertIn(mock.call(['identity']), m_sman_cli.call_args_list) self.assertIn(mock.call(['register', '--username=scooby@do.com', '--password=scooby-snacks'], logstring_val=True), m_sman_cli.call_args_list) self.assertIn('rh_subscription plugin completed successfully', self.logs.getvalue()) self.assertEqual(m_sman_cli.call_count, 2) @mock.patch.object(cc_rh_subscription.SubscriptionManager, "_getRepos") def test_update_repos_disable_with_none(self, m_get_repos, m_sman_cli): cfg = copy.deepcopy(self.config) m_get_repos.return_value = ([], ['repo1']) cfg['rh_subscription'].update( {'enable-repo': ['repo1'], 'disable-repo': None}) mysm = cc_rh_subscription.SubscriptionManager(cfg) self.assertEqual(True, mysm.update_repos()) m_get_repos.assert_called_with() self.assertEqual(m_sman_cli.call_args_list, [mock.call(['repos', '--enable=repo1'])]) def test_full_registration(self, m_sman_cli): ''' Registration with auto-attach, service-level, adding pools, and enabling and disabling yum repos ''' call_lists = [] call_lists.append(['attach', '--pool=pool1', '--pool=pool3']) call_lists.append(['repos', '--disable=repo5', '--enable=repo2', '--enable=repo3']) call_lists.append(['attach', '--auto', '--servicelevel=self-support']) reg = "The system has been registered with ID:" \ " 12345678-abde-abcde-1234-1234567890abc" m_sman_cli.side_effect = [ subp.ProcessExecutionError, (reg, 'bar'), ('Service level set to: self-support', ''), ('pool1\npool3\n', ''), ('pool2\n', ''), ('', ''), ('Repo ID: repo1\nRepo ID: repo5\n', ''), ('Repo ID: repo2\nRepo ID: repo3\nRepo ID: repo4', ''), ('', '')] self.handle(self.name, self.config_full, self.cloud_init, self.log, self.args) self.assertEqual(m_sman_cli.call_count, 9) for call in call_lists: self.assertIn(mock.call(call), m_sman_cli.call_args_list) self.assertIn("rh_subscription plugin completed successfully", self.logs.getvalue()) @mock.patch(SUB_MAN_CLI) class TestBadInput(CiTestCase): with_logs = True name = "cc_rh_subscription" cloud_init = None log = logging.getLogger("bad_tests") args = [] SM = cc_rh_subscription.SubscriptionManager reg = "The system has been registered with ID:" \ " 12345678-abde-abcde-1234-1234567890abc" config_no_password = {'rh_subscription': {'username': 'scooby@do.com' }} config_no_key = {'rh_subscription': {'activation-key': '1234abcde', }} config_service = {'rh_subscription': {'username': 'scooby@do.com', 'password': 'scooby-snacks', 'service-level': 'self-support' }} config_badpool = {'rh_subscription': {'username': 'scooby@do.com', 'password': 'scooby-snacks', 'add-pool': 'not_a_list' }} config_badrepo = {'rh_subscription': {'username': 'scooby@do.com', 'password': 'scooby-snacks', 'enable-repo': 'not_a_list' }} config_badkey = {'rh_subscription': {'activation-key': 'abcdef1234', 'fookey': 'bar', 'org': '123', }} def setUp(self): super(TestBadInput, self).setUp() self.handle = cc_rh_subscription.handle def assert_logged_warnings(self, warnings): logs = self.logs.getvalue() missing = [w for w in warnings if "WARNING: " + w not in logs] self.assertEqual([], missing, "Missing expected warnings.") def test_no_password(self, m_sman_cli): '''Attempt to register without the password key/value.''' m_sman_cli.side_effect = [subp.ProcessExecutionError, (self.reg, 'bar')] self.handle(self.name, self.config_no_password, self.cloud_init, self.log, self.args) self.assertEqual(m_sman_cli.call_count, 0) def test_no_org(self, m_sman_cli): '''Attempt to register without the org key/value.''' m_sman_cli.side_effect = [subp.ProcessExecutionError] self.handle(self.name, self.config_no_key, self.cloud_init, self.log, self.args) m_sman_cli.assert_called_with(['identity']) self.assertEqual(m_sman_cli.call_count, 1) self.assert_logged_warnings(( 'Unable to register system due to incomplete information.', 'Use either activationkey and org *or* userid and password', 'Registration failed or did not run completely', 'rh_subscription plugin did not complete successfully')) def test_service_level_without_auto(self, m_sman_cli): '''Attempt to register using service-level without auto-attach key.''' m_sman_cli.side_effect = [subp.ProcessExecutionError, (self.reg, 'bar')] self.handle(self.name, self.config_service, self.cloud_init, self.log, self.args) self.assertEqual(m_sman_cli.call_count, 1) self.assert_logged_warnings(( 'The service-level key must be used in conjunction with ', 'rh_subscription plugin did not complete successfully')) def test_pool_not_a_list(self, m_sman_cli): ''' Register with pools that are not in the format of a list ''' m_sman_cli.side_effect = [subp.ProcessExecutionError, (self.reg, 'bar')] self.handle(self.name, self.config_badpool, self.cloud_init, self.log, self.args) self.assertEqual(m_sman_cli.call_count, 2) self.assert_logged_warnings(( 'Pools must in the format of a list', 'rh_subscription plugin did not complete successfully')) def test_repo_not_a_list(self, m_sman_cli): ''' Register with repos that are not in the format of a list ''' m_sman_cli.side_effect = [subp.ProcessExecutionError, (self.reg, 'bar')] self.handle(self.name, self.config_badrepo, self.cloud_init, self.log, self.args) self.assertEqual(m_sman_cli.call_count, 2) self.assert_logged_warnings(( 'Repo IDs must in the format of a list.', 'Unable to add or remove repos', 'rh_subscription plugin did not complete successfully')) def test_bad_key_value(self, m_sman_cli): ''' Attempt to register with a key that we don't know ''' m_sman_cli.side_effect = [subp.ProcessExecutionError, (self.reg, 'bar')] self.handle(self.name, self.config_badkey, self.cloud_init, self.log, self.args) self.assertEqual(m_sman_cli.call_count, 1) self.assert_logged_warnings(( 'fookey is not a valid key for rh_subscription. Valid keys are:', 'rh_subscription plugin did not complete successfully')) # vi: ts=4 expandtab