diff --git a/changelogs/fragments/redhat_subscribtion.yml b/changelogs/fragments/redhat_subscribtion.yml new file mode 100644 index 00000000000..0791d35b2ce --- /dev/null +++ b/changelogs/fragments/redhat_subscribtion.yml @@ -0,0 +1,5 @@ +bugfixes: + - redhat_subscription - made code compatible with Python3 (https://github.com/ansible/ansible/pull/58665) +minor_changes: + - redhat_subscription - do not call ``subscribtion-manager`` command, when it is not necessary (https://github.com/ansible/ansible/pull/58665) + - redhat_subscription - made code more testable (https://github.com/ansible/ansible/pull/58665) \ No newline at end of file diff --git a/lib/ansible/modules/packaging/os/redhat_subscription.py b/lib/ansible/modules/packaging/os/redhat_subscription.py index fa1beb57282..ad6b55fc25f 100644 --- a/lib/ansible/modules/packaging/os/redhat_subscription.py +++ b/lib/ansible/modules/packaging/os/redhat_subscription.py @@ -227,6 +227,9 @@ SUBMAN_CMD = None class RegistrationBase(object): + + REDHAT_REPO = "/etc/yum.repos.d/redhat.repo" + def __init__(self, module, username=None, password=None): self.module = module self.username = username @@ -237,9 +240,8 @@ class RegistrationBase(object): def enable(self): # Remove any existing redhat.repo - redhat_repo = '/etc/yum.repos.d/redhat.repo' - if os.path.isfile(redhat_repo): - os.unlink(redhat_repo) + if os.path.isfile(self.REDHAT_REPO): + os.unlink(self.REDHAT_REPO) def register(self): raise NotImplementedError("Must be implemented by a sub-class") @@ -294,14 +296,24 @@ class Rhsm(RegistrationBase): Raises: * Exception - if error occurs while running command ''' + args = [SUBMAN_CMD, 'config'] # Pass supplied **kwargs as parameters to subscription-manager. Ignore # non-configuration parameters and replace '_' with '.'. For example, # 'server_hostname' becomes '--server.hostname'. - for k, v in kwargs.items(): + options = [] + for k, v in sorted(kwargs.items()): if re.search(r'^(server|rhsm)_', k) and v is not None: - args.append('--%s=%s' % (k.replace('_', '.', 1), v)) + options.append('--%s=%s' % (k.replace('_', '.', 1), v)) + + # When there is nothing to configure, then it is not necessary + # to run config command, because it only returns current + # content of current configuration file + if len(options) == 0: + return + + args.extend(options) self.module.run_command(args, check_rc=True) @@ -449,9 +461,19 @@ class Rhsm(RegistrationBase): return [] def subscribe_by_pool_ids(self, pool_ids): - for pool_id, quantity in pool_ids.items(): - args = [SUBMAN_CMD, 'attach', '--pool', pool_id, '--quantity', quantity] - rc, stderr, stdout = self.module.run_command(args, check_rc=True) + """ + Try to subscribe to the list of pool IDs + """ + available_pools = RhsmPools(self.module) + + available_pool_ids = [p.get_pool_id() for p in available_pools] + + for pool_id, quantity in sorted(pool_ids.items()): + if pool_id in available_pool_ids: + args = [SUBMAN_CMD, 'attach', '--pool', pool_id, '--quantity', quantity] + rc, stderr, stdout = self.module.run_command(args, check_rc=True) + else: + self.module.fail_json(msg='Pool ID: %s not in list of available pools' % pool_id) return pool_ids def subscribe_pool(self, regexp): @@ -516,7 +538,7 @@ class Rhsm(RegistrationBase): serials = self.unsubscribe(serials=serials_to_remove) missing_pools = {} - for pool_id, quantity in pool_ids.items(): + for pool_id, quantity in sorted(pool_ids.items()): if existing_pools.get(pool_id, 0) != quantity: missing_pools[pool_id] = quantity @@ -545,7 +567,7 @@ class RhsmPool(object): return getattr(self, 'PoolId', getattr(self, 'PoolID')) def subscribe(self): - args = "subscription-manager subscribe --pool %s" % self.get_pool_id() + args = "subscription-manager attach --pool %s" % self.get_pool_id() rc, stdout, stderr = self.module.run_command(args, check_rc=True) if rc == 0: return True @@ -710,7 +732,7 @@ def main(): if isinstance(value, dict): if len(value) != 1: module.fail_json(msg='Unable to parse pool_ids option.') - pool_id, quantity = value.items()[0] + pool_id, quantity = list(value.items())[0] else: pool_id, quantity = value, 1 pool_ids[pool_id] = str(quantity) @@ -754,8 +776,10 @@ def main(): server_proxy_hostname, server_proxy_port, server_proxy_user, server_proxy_password, release) if pool_ids: subscribed_pool_ids = rhsm.subscribe_by_pool_ids(pool_ids) - else: + elif pool != '^$': subscribed_pool_ids = rhsm.subscribe(pool) + else: + subscribed_pool_ids = [] except Exception as e: module.fail_json(msg="Failed to register with '%s': %s" % (server_hostname, to_native(e))) else: diff --git a/test/units/modules/packaging/os/test_redhat_subscription.py b/test/units/modules/packaging/os/test_redhat_subscription.py new file mode 100644 index 00000000000..8e9beca7019 --- /dev/null +++ b/test/units/modules/packaging/os/test_redhat_subscription.py @@ -0,0 +1,851 @@ +# Author: Jiri Hnidek (jhnidek@redhat.com) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + +from ansible.module_utils import basic +from ansible.modules.packaging.os import redhat_subscription + +import pytest + +TESTED_MODULE = redhat_subscription.__name__ + + +@pytest.fixture +def patch_redhat_subscription(mocker): + """ + Function used for mocking some parts of redhat_subscribtion module + """ + mocker.patch('ansible.modules.packaging.os.redhat_subscription.RegistrationBase.REDHAT_REPO') + mocker.patch('os.path.isfile', return_value=False) + mocker.patch('os.unlink', return_value=True) + mocker.patch('ansible.modules.packaging.os.redhat_subscription.AnsibleModule.get_bin_path', + return_value='/testbin/subscription-manager') + + +@pytest.mark.parametrize('patch_ansible_module', [{}], indirect=['patch_ansible_module']) +@pytest.mark.usefixtures('patch_ansible_module') +def test_without_required_parameters(capfd, patch_redhat_subscription): + """ + Failure must occurs when all parameters are missing + """ + with pytest.raises(SystemExit): + redhat_subscription.main() + out, err = capfd.readouterr() + results = json.loads(out) + assert results['failed'] + assert 'state is present but any of the following are missing' in results['msg'] + + +TEST_CASES = [ + # Test the case, when the system is already registered + [ + { + 'state': 'present', + 'server_hostname': 'subscription.rhsm.redhat.com', + 'username': 'admin', + 'password': 'admin', + 'org_id': 'admin' + }, + { + 'id': 'test_already_registered_system', + 'run_command.calls': [ + ( + # Calling of following command will be asserted + ['/testbin/subscription-manager', 'identity'], + # Was return code checked? + {'check_rc': False}, + # Mock of returned code, stdout and stderr + (0, 'system identity: b26df632-25ed-4452-8f89-0308bfd167cb', '') + ) + ], + 'changed': False, + 'msg': 'System already registered.' + } + ], + # Test simple registration using username and password + [ + { + 'state': 'present', + 'server_hostname': 'satellite.company.com', + 'username': 'admin', + 'password': 'admin', + }, + { + 'id': 'test_registeration_username_password', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (1, '', '') + ), + ( + ['/testbin/subscription-manager', 'config', '--server.hostname=satellite.company.com'], + {'check_rc': True}, + (0, '', '') + ), + ( + ['/testbin/subscription-manager', 'register', + '--serverurl', 'satellite.company.com', + '--username', 'admin', + '--password', 'admin'], + {'check_rc': True, 'expand_user_and_vars': False}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully registered to 'satellite.company.com'." + } + ], + # Test unregistration, when system is unregistered + [ + { + 'state': 'absent', + 'server_hostname': 'subscription.rhsm.redhat.com', + 'username': 'admin', + 'password': 'admin', + }, + { + 'id': 'test_unregisteration', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (0, 'system identity: b26df632-25ed-4452-8f89-0308bfd167cb', '') + ), + ( + ['/testbin/subscription-manager', 'unsubscribe', '--all'], + {'check_rc': True}, + (0, '', '') + ), + ( + ['/testbin/subscription-manager', 'unregister'], + {'check_rc': True}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully unregistered from subscription.rhsm.redhat.com." + } + ], + # Test unregistration of already unregistered system + [ + { + 'state': 'absent', + 'server_hostname': 'subscription.rhsm.redhat.com', + 'username': 'admin', + 'password': 'admin', + }, + { + 'id': 'test_unregisteration_of_unregistered_system', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (1, 'This system is not yet registered.', '') + ) + ], + 'changed': False, + 'msg': "System already unregistered." + } + ], + # Test registration using activation key + [ + { + 'state': 'present', + 'server_hostname': 'satellite.company.com', + 'activationkey': 'some-activation-key', + 'org_id': 'admin' + }, + { + 'id': 'test_registeration_activation_key', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (1, 'This system is not yet registered.', '') + ), + ( + ['/testbin/subscription-manager', 'config', '--server.hostname=satellite.company.com'], + {'check_rc': True}, + (0, '', '') + ), + ( + [ + '/testbin/subscription-manager', + 'register', + '--serverurl', 'satellite.company.com', + '--org', 'admin', + '--activationkey', 'some-activation-key' + ], + {'check_rc': True, 'expand_user_and_vars': False}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully registered to 'satellite.company.com'." + } + ], + # Test of registration using username and password with auto-attach option + [ + { + 'state': 'present', + 'username': 'admin', + 'password': 'admin', + 'org_id': 'admin', + 'auto_attach': 'true' + }, + { + 'id': 'test_registeration_username_password_auto_attach', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (1, 'This system is not yet registered.', '') + ), + ( + [ + '/testbin/subscription-manager', + 'register', + '--org', 'admin', + '--auto-attach', + '--username', 'admin', + '--password', 'admin' + ], + {'check_rc': True, 'expand_user_and_vars': False}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully registered to 'None'." + } + ], + # Test of force registration despite the system is already registered + [ + { + 'state': 'present', + 'username': 'admin', + 'password': 'admin', + 'org_id': 'admin', + 'force_register': 'true' + }, + { + 'id': 'test_force_registeration_username_password', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (0, 'This system already registered.', '') + ), + ( + [ + '/testbin/subscription-manager', + 'register', + '--force', + '--org', 'admin', + '--username', 'admin', + '--password', 'admin' + ], + {'check_rc': True, 'expand_user_and_vars': False}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully registered to 'None'." + } + ], + # Test of registration using username, password and proxy options + [ + { + 'state': 'present', + 'username': 'admin', + 'password': 'admin', + 'org_id': 'admin', + 'force_register': 'true', + 'server_proxy_hostname': 'proxy.company.com', + 'server_proxy_port': '12345', + 'server_proxy_user': 'proxy_user', + 'server_proxy_password': 'secret_proxy_password' + }, + { + 'id': 'test_registeration_username_password_proxy_options', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (0, 'This system already registered.', '') + ), + ( + [ + '/testbin/subscription-manager', + 'config', + '--server.proxy_hostname=proxy.company.com', + '--server.proxy_password=secret_proxy_password', + '--server.proxy_port=12345', + '--server.proxy_user=proxy_user' + ], + {'check_rc': True}, + (0, '', '') + ), + ( + [ + '/testbin/subscription-manager', + 'register', + '--force', + '--org', 'admin', + '--proxy', 'proxy.company.com:12345', + '--proxyuser', 'proxy_user', + '--proxypassword', 'secret_proxy_password', + '--username', 'admin', + '--password', 'admin' + ], + {'check_rc': True, 'expand_user_and_vars': False}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully registered to 'None'." + } + ], + # Test of registration using username and password and attach to pool + [ + { + 'state': 'present', + 'username': 'admin', + 'password': 'admin', + 'org_id': 'admin', + 'pool': 'ff8080816b8e967f016b8e99632804a6' + }, + { + 'id': 'test_registeration_username_password_pool', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (1, 'This system is not yet registered.', '') + ), + ( + [ + '/testbin/subscription-manager', + 'register', + '--org', 'admin', + '--username', 'admin', + '--password', 'admin' + ], + {'check_rc': True, 'expand_user_and_vars': False}, + (0, '', '') + ), + ( + [ + 'subscription-manager list --available', + {'check_rc': True, 'environ_update': {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}}, + (0, + ''' ++-------------------------------------------+ + Available Subscriptions ++-------------------------------------------+ +Subscription Name: SP Server Premium (S: Premium, U: Production, R: SP Server) +Provides: SP Server Bits +SKU: sp-server-prem-prod +Contract: 0 +Pool ID: ff8080816b8e967f016b8e99632804a6 +Provides Management: Yes +Available: 5 +Suggested: 1 +Service Type: L1-L3 +Roles: SP Server +Service Level: Premium +Usage: Production +Add-ons: +Subscription Type: Standard +Starts: 06/25/19 +Ends: 06/24/20 +Entitlement Type: Physical +''', ''), + ] + ), + ( + 'subscription-manager attach --pool ff8080816b8e967f016b8e99632804a6', + {'check_rc': True}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully registered to 'None'." + } + ], + # Test of registration using username and password and attach to pool ID and quantities + [ + { + 'state': 'present', + 'username': 'admin', + 'password': 'admin', + 'org_id': 'admin', + 'pool_ids': [{'ff8080816b8e967f016b8e99632804a6': 2}, {'ff8080816b8e967f016b8e99747107e9': 4}] + }, + { + 'id': 'test_registeration_username_password_pool_ids_quantities', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (1, 'This system is not yet registered.', '') + ), + ( + [ + '/testbin/subscription-manager', + 'register', + '--org', 'admin', + '--username', 'admin', + '--password', 'admin' + ], + {'check_rc': True, 'expand_user_and_vars': False}, + (0, '', '') + ), + ( + [ + 'subscription-manager list --available', + {'check_rc': True, 'environ_update': {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}}, + (0, + ''' ++-------------------------------------------+ + Available Subscriptions ++-------------------------------------------+ +Subscription Name: SP Smart Management (A: ADDON1) +Provides: SP Addon 1 bits +SKU: sp-with-addon-1 +Contract: 1 +Pool ID: ff8080816b8e967f016b8e99747107e9 +Provides Management: Yes +Available: 10 +Suggested: 1 +Service Type: +Roles: +Service Level: +Usage: +Add-ons: ADDON1 +Subscription Type: Standard +Starts: 25.6.2019 +Ends: 24.6.2020 +Entitlement Type: Physical + +Subscription Name: SP Server Premium (S: Premium, U: Production, R: SP Server) +Provides: SP Server Bits +SKU: sp-server-prem-prod +Contract: 0 +Pool ID: ff8080816b8e967f016b8e99632804a6 +Provides Management: Yes +Available: 5 +Suggested: 1 +Service Type: L1-L3 +Roles: SP Server +Service Level: Premium +Usage: Production +Add-ons: +Subscription Type: Standard +Starts: 06/25/19 +Ends: 06/24/20 +Entitlement Type: Physical +''', '') + ] + ), + ( + [ + '/testbin/subscription-manager', + 'attach', + '--pool', 'ff8080816b8e967f016b8e99632804a6', + '--quantity', '2' + ], + {'check_rc': True}, + (0, '', '') + ), + ( + [ + '/testbin/subscription-manager', + 'attach', + '--pool', 'ff8080816b8e967f016b8e99747107e9', + '--quantity', '4' + ], + {'check_rc': True}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully registered to 'None'." + } + ], + # Test of registration using username and password and attach to pool ID without quantities + [ + { + 'state': 'present', + 'username': 'admin', + 'password': 'admin', + 'org_id': 'admin', + 'pool_ids': ['ff8080816b8e967f016b8e99632804a6', 'ff8080816b8e967f016b8e99747107e9'] + }, + { + 'id': 'test_registeration_username_password_pool_ids', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (1, 'This system is not yet registered.', '') + ), + ( + [ + '/testbin/subscription-manager', + 'register', + '--org', 'admin', + '--username', 'admin', + '--password', 'admin' + ], + {'check_rc': True, 'expand_user_and_vars': False}, + (0, '', '') + ), + ( + [ + 'subscription-manager list --available', + {'check_rc': True, 'environ_update': {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}}, + (0, + ''' ++-------------------------------------------+ + Available Subscriptions ++-------------------------------------------+ +Subscription Name: SP Smart Management (A: ADDON1) +Provides: SP Addon 1 bits +SKU: sp-with-addon-1 +Contract: 1 +Pool ID: ff8080816b8e967f016b8e99747107e9 +Provides Management: Yes +Available: 10 +Suggested: 1 +Service Type: +Roles: +Service Level: +Usage: +Add-ons: ADDON1 +Subscription Type: Standard +Starts: 25.6.2019 +Ends: 24.6.2020 +Entitlement Type: Physical + +Subscription Name: SP Server Premium (S: Premium, U: Production, R: SP Server) +Provides: SP Server Bits +SKU: sp-server-prem-prod +Contract: 0 +Pool ID: ff8080816b8e967f016b8e99632804a6 +Provides Management: Yes +Available: 5 +Suggested: 1 +Service Type: L1-L3 +Roles: SP Server +Service Level: Premium +Usage: Production +Add-ons: +Subscription Type: Standard +Starts: 06/25/19 +Ends: 06/24/20 +Entitlement Type: Physical +''', '') + ] + ), + ( + [ + '/testbin/subscription-manager', + 'attach', + '--pool', 'ff8080816b8e967f016b8e99632804a6', + '--quantity', '1' + ], + {'check_rc': True}, + (0, '', '') + ), + ( + [ + '/testbin/subscription-manager', + 'attach', + '--pool', 'ff8080816b8e967f016b8e99747107e9', + '--quantity', '1' + ], + {'check_rc': True}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully registered to 'None'." + } + ], + # Test of registration using username and password and attach to pool ID (one pool) + [ + { + 'state': 'present', + 'username': 'admin', + 'password': 'admin', + 'org_id': 'admin', + 'pool_ids': ['ff8080816b8e967f016b8e99632804a6'] + }, + { + 'id': 'test_registeration_username_password_one_pool_id', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (1, 'This system is not yet registered.', '') + ), + ( + [ + '/testbin/subscription-manager', + 'register', + '--org', 'admin', + '--username', 'admin', + '--password', 'admin' + ], + {'check_rc': True, 'expand_user_and_vars': False}, + (0, '', '') + ), + ( + [ + 'subscription-manager list --available', + {'check_rc': True, 'environ_update': {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}}, + (0, + ''' ++-------------------------------------------+ + Available Subscriptions ++-------------------------------------------+ +Subscription Name: SP Smart Management (A: ADDON1) +Provides: SP Addon 1 bits +SKU: sp-with-addon-1 +Contract: 1 +Pool ID: ff8080816b8e967f016b8e99747107e9 +Provides Management: Yes +Available: 10 +Suggested: 1 +Service Type: +Roles: +Service Level: +Usage: +Add-ons: ADDON1 +Subscription Type: Standard +Starts: 25.6.2019 +Ends: 24.6.2020 +Entitlement Type: Physical + +Subscription Name: SP Server Premium (S: Premium, U: Production, R: SP Server) +Provides: SP Server Bits +SKU: sp-server-prem-prod +Contract: 0 +Pool ID: ff8080816b8e967f016b8e99632804a6 +Provides Management: Yes +Available: 5 +Suggested: 1 +Service Type: L1-L3 +Roles: SP Server +Service Level: Premium +Usage: Production +Add-ons: +Subscription Type: Standard +Starts: 06/25/19 +Ends: 06/24/20 +Entitlement Type: Physical +''', '') + ] + ), + ( + [ + '/testbin/subscription-manager', + 'attach', + '--pool', 'ff8080816b8e967f016b8e99632804a6', + '--quantity', '1' + ], + {'check_rc': True}, + (0, '', '') + ) + ], + 'changed': True, + 'msg': "System successfully registered to 'None'." + } + ], + # Test attaching different set of pool IDs + [ + { + 'state': 'present', + 'username': 'admin', + 'password': 'admin', + 'org_id': 'admin', + 'pool_ids': [{'ff8080816b8e967f016b8e99632804a6': 2}, {'ff8080816b8e967f016b8e99747107e9': 4}] + }, + { + 'id': 'test_attaching_different_pool_ids', + 'run_command.calls': [ + ( + ['/testbin/subscription-manager', 'identity'], + {'check_rc': False}, + (0, 'system identity: b26df632-25ed-4452-8f89-0308bfd167cb', ''), + ), + ( + 'subscription-manager list --consumed', + {'check_rc': True, 'environ_update': {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}}, + (0, ''' ++-------------------------------------------+ + Consumed Subscriptions ++-------------------------------------------+ +Subscription Name: Multi-Attribute Stackable (4 cores, no content) +Provides: Multi-Attribute Limited Product (no content) +SKU: cores4-multiattr +Contract: 1 +Account: 12331131231 +Serial: 7807912223970164816 +Pool ID: ff8080816b8e967f016b8e995f5103b5 +Provides Management: No +Active: True +Quantity Used: 1 +Service Type: Level 3 +Roles: +Service Level: Premium +Usage: +Add-ons: +Status Details: Subscription is current +Subscription Type: Stackable +Starts: 06/25/19 +Ends: 06/24/20 +Entitlement Type: Physical +''', '') + ), + ( + [ + '/testbin/subscription-manager', + 'unsubscribe', + '--serial=7807912223970164816', + ], + {'check_rc': True}, + (0, '', '') + ), + ( + [ + 'subscription-manager list --available', + {'check_rc': True, 'environ_update': {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}}, + (0, + ''' ++-------------------------------------------+ + Available Subscriptions ++-------------------------------------------+ +Subscription Name: SP Smart Management (A: ADDON1) +Provides: SP Addon 1 bits +SKU: sp-with-addon-1 +Contract: 1 +Pool ID: ff8080816b8e967f016b8e99747107e9 +Provides Management: Yes +Available: 10 +Suggested: 1 +Service Type: +Roles: +Service Level: +Usage: +Add-ons: ADDON1 +Subscription Type: Standard +Starts: 25.6.2019 +Ends: 24.6.2020 +Entitlement Type: Physical + +Subscription Name: SP Server Premium (S: Premium, U: Production, R: SP Server) +Provides: SP Server Bits +SKU: sp-server-prem-prod +Contract: 0 +Pool ID: ff8080816b8e967f016b8e99632804a6 +Provides Management: Yes +Available: 5 +Suggested: 1 +Service Type: L1-L3 +Roles: SP Server +Service Level: Premium +Usage: Production +Add-ons: +Subscription Type: Standard +Starts: 06/25/19 +Ends: 06/24/20 +Entitlement Type: Physical + +Subscription Name: Multi-Attribute Stackable (4 cores, no content) +Provides: Multi-Attribute Limited Product (no content) +SKU: cores4-multiattr +Contract: 1 +Pool ID: ff8080816b8e967f016b8e995f5103b5 +Provides Management: No +Available: 10 +Suggested: 1 +Service Type: Level 3 +Roles: +Service Level: Premium +Usage: +Add-ons: +Subscription Type: Stackable +Starts: 11.7.2019 +Ends: 10.7.2020 +Entitlement Type: Physical +''', '') + ] + ), + ( + [ + '/testbin/subscription-manager', + 'attach', + '--pool', 'ff8080816b8e967f016b8e99632804a6', + '--quantity', '2' + ], + {'check_rc': True}, + (0, '', '') + ), + ( + [ + '/testbin/subscription-manager', + 'attach', + '--pool', 'ff8080816b8e967f016b8e99747107e9', + '--quantity', '4' + ], + {'check_rc': True}, + (0, '', '') + ) + ], + 'changed': True, + } + ], +] + + +TEST_CASES_IDS = [item[1]['id'] for item in TEST_CASES] + + +@pytest.mark.parametrize('patch_ansible_module, testcase', TEST_CASES, ids=TEST_CASES_IDS, indirect=['patch_ansible_module']) +@pytest.mark.usefixtures('patch_ansible_module') +def test_redhat_subscribtion(mocker, capfd, patch_redhat_subscription, testcase): + """ + Run unit tests for test cases listen in TEST_CASES + """ + + # Mock function used for running commands first + call_results = [item[2] for item in testcase['run_command.calls']] + mock_run_command = mocker.patch.object( + basic.AnsibleModule, + 'run_command', + side_effect=call_results) + + # Try to run test case + with pytest.raises(SystemExit): + redhat_subscription.main() + + out, err = capfd.readouterr() + results = json.loads(out) + + assert 'changed' in results + assert results['changed'] == testcase['changed'] + if 'msg' in results: + assert results['msg'] == testcase['msg'] + + assert basic.AnsibleModule.run_command.call_count == len(testcase['run_command.calls']) + if basic.AnsibleModule.run_command.call_count: + call_args_list = [(item[0][0], item[1]) for item in basic.AnsibleModule.run_command.call_args_list] + expected_call_args_list = [(item[0], item[1]) for item in testcase['run_command.calls']] + assert call_args_list == expected_call_args_list