ansible-collections.communi.../tests/unit/plugins/modules/test_api_facts.py
Felix Fontein 30a79061f3
Use shared unit test utils from community.internal_test_tools (#353)
* Use shared unit test utils from community.internal_test_tools.

* Make sure community.internal_test_tools is installed in CI.
2025-03-12 21:34:12 +01:00

753 lines
25 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import patch, MagicMock
from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase
from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, fake_ros_api
from ansible_collections.community.routeros.plugins.modules import api_facts
API_RESPONSES = {
('interface', ): [
{
'.id': '*1',
'name': 'first-ether',
'default-name': 'ether1',
'type': 'ether',
'mtu': 1500,
'actual-mtu': 1500,
'l2mtu': 1598,
'max-l2mtu': 4074,
'mac-address': '00:11:22:33:44:55',
'last-link-up-time': 'apr/22/2022 07:54:55',
'link-downs': 0,
'rx-byte': 1234,
'tx-byte': 1234,
'rx-packet': 1234,
'tx-packet': 1234,
'rx-drop': 1234,
'tx-drop': 1234,
'tx-queue-drop': 1234,
'rx-error': 1234,
'tx-error': 1234,
'fp-rx-byte': 1234,
'fp-tx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-packet': 1234,
'running': True,
'disabled': False,
},
{
'.id': '*2',
'name': 'second-ether',
'default-name': 'ether2',
'type': 'ether',
'mtu': 1500,
'actual-mtu': 1500,
'l2mtu': 1598,
'max-l2mtu': 4074,
'mac-address': '00:11:22:33:44:66',
'last-link-up-time': 'apr/22/2022 07:54:55',
'link-downs': 0,
'rx-byte': 1234,
'tx-byte': 1234,
'rx-packet': 1234,
'tx-packet': 1234,
'rx-drop': 1234,
'tx-drop': 1234,
'tx-queue-drop': 1234,
'rx-error': 1234,
'tx-error': 1234,
'fp-rx-byte': 1234,
'fp-tx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-packet': 1234,
'running': True,
'slave': True,
'disabled': False,
},
{
'.id': '*3',
'name': 'third-ether',
'default-name': 'ether3',
'type': 'ether',
'mtu': 1500,
'actual-mtu': 1500,
'l2mtu': 1598,
'max-l2mtu': 4074,
'mac-address': '00:11:22:33:44:77',
'last-link-up-time': 'apr/22/2022 07:54:55',
'link-downs': 0,
'rx-byte': 1234,
'tx-byte': 1234,
'rx-packet': 1234,
'tx-packet': 1234,
'rx-drop': 1234,
'tx-drop': 1234,
'tx-queue-drop': 1234,
'rx-error': 1234,
'tx-error': 1234,
'fp-rx-byte': 1234,
'fp-tx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-packet': 1234,
'running': True,
'slave': True,
'disabled': False,
},
{
'.id': '*4',
'name': 'fourth-ether',
'default-name': 'ether4',
'type': 'ether',
'mtu': 1500,
'actual-mtu': 1500,
'l2mtu': 1598,
'max-l2mtu': 4074,
'mac-address': '00:11:22:33:44:88',
'last-link-down-time': 'apr/23/2022 08:22:50',
'last-link-up-time': 'apr/23/2022 08:22:52',
'link-downs': 2,
'rx-byte': 1234,
'tx-byte': 1234,
'rx-packet': 1234,
'tx-packet': 1234,
'rx-drop': 1234,
'tx-drop': 1234,
'tx-queue-drop': 1234,
'rx-error': 1234,
'tx-error': 1234,
'fp-rx-byte': 1234,
'fp-tx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-packet': 1234,
'running': True,
'disabled': False,
},
{
'.id': '*5',
'name': 'fifth-ether',
'default-name': 'ether5',
'type': 'ether',
'mtu': 1500,
'actual-mtu': 1500,
'l2mtu': 1598,
'max-l2mtu': 4074,
'mac-address': '00:11:22:33:44:99',
'last-link-down-time': 'may/02/2022 18:12:32',
'last-link-up-time': 'may/02/2022 18:08:01',
'link-downs': 14,
'rx-byte': 1234,
'tx-byte': 1234,
'rx-packet': 1234,
'tx-packet': 1234,
'rx-drop': 1234,
'tx-drop': 1234,
'tx-queue-drop': 1234,
'rx-error': 1234,
'tx-error': 1234,
'fp-rx-byte': 1234,
'fp-tx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-packet': 1234,
'running': False,
'slave': True,
'disabled': False,
},
{
'.id': '*7',
'name': 'my-bridge',
'type': 'bridge',
'mtu': 'auto',
'actual-mtu': 1500,
'l2mtu': 1598,
'mac-address': '00:11:22:33:44:66',
'last-link-up-time': 'apr/22/2022 07:54:48',
'link-downs': 0,
'rx-byte': 1234,
'tx-byte': 1234,
'rx-packet': 1234,
'tx-packet': 1234,
'rx-drop': 1234,
'tx-drop': 1234,
'tx-queue-drop': 1234,
'rx-error': 1234,
'tx-error': 1234,
'fp-rx-byte': 1234,
'fp-tx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-packet': 1234,
'running': True,
'disabled': False,
},
],
('ip', 'address', ): [
{
'.id': '*1',
'address': '192.168.1.1/24',
'network': '192.168.1.0',
'interface': 'my-bridge',
'actual-interface': 'my-bridge',
'invalid': False,
'dynamic': False,
'disabled': False,
'comment': 'Wohnung',
},
{
'.id': '*5',
'address': '192.168.2.1/24',
'network': '192.168.2.0',
'interface': 'fourth-ether',
'actual-interface': 'fourth-ether',
'invalid': False,
'dynamic': False,
'disabled': False,
'comment': 'VoIP',
},
{
'.id': '*6',
'address': '1.2.3.4/21',
'network': '84.73.216.0',
'interface': 'first-ether',
'actual-interface': 'first-ether',
'invalid': False,
'dynamic': True,
'disabled': False,
},
],
('ipv6', 'address', ): [
{
'.id': '*1',
'address': 'fe80::1:2:3/64',
'from-pool': '',
'interface': 'my-bridge',
'actual-interface': 'my-bridge',
'eui-64': False,
'advertise': False,
'no-dad': False,
'invalid': False,
'dynamic': True,
'link-local': True,
'disabled': False,
},
{
'.id': '*2',
'address': 'fe80::1:2:4/64',
'from-pool': '',
'interface': 'fourth-ether',
'actual-interface': 'fourth-ether',
'eui-64': False,
'advertise': False,
'no-dad': False,
'invalid': False,
'dynamic': True,
'link-local': True,
'disabled': False,
},
{
'.id': '*3',
'address': 'fe80::1:2:5/64',
'from-pool': '',
'interface': 'first-ether',
'actual-interface': 'first-ether',
'eui-64': False,
'advertise': False,
'no-dad': False,
'invalid': False,
'dynamic': True,
'link-local': True,
'disabled': False,
},
],
('ip', 'neighbor', ): [],
('system', 'identity', ): [
{
'name': 'MikroTik',
},
],
('system', 'resource', ): [
{
'uptime': '2w3d4h5m6s',
'version': '6.49.6 (stable)',
'build-time': 'Apr/07/2022 17:53:31',
'free-memory': 12345678,
'total-memory': 23456789,
'cpu': 'MIPS 24Kc V7.4',
'cpu-count': 1,
'cpu-frequency': 400,
'cpu-load': 48,
'free-hdd-space': 123456789,
'total-hdd-space': 234567890,
'write-sect-since-reboot': 1234,
'write-sect-total': 12345,
'bad-blocks': 0,
'architecture-name': 'mipsbe',
'board-name': 'RB750GL',
'platform': 'MikroTik',
},
],
('system', 'routerboard', ): [
{
'routerboard': True,
'model': '750GL',
'serial-number': '0123456789AB',
'firmware-type': 'ar7240',
'factory-firmware': '3.09',
'current-firmware': '6.49.6',
'upgrade-firmware': '6.49.6',
},
],
('routing', 'bgp', 'peer', ): [],
('routing', 'bgp', 'vpnv4-route', ): [],
('routing', 'bgp', 'instance', ): [
{
'.id': '*0',
'name': 'default',
'as': 65530,
'router-id': '0.0.0.0',
'redistribute-connected': False,
'redistribute-static': False,
'redistribute-rip': False,
'redistribute-ospf': False,
'redistribute-other-bgp': False,
'out-filter': '',
'client-to-client-reflection': True,
'ignore-as-path-len': False,
'routing-table': '',
'default': True,
'disabled': False,
},
],
('ip', 'route', ): [
{
'.id': '*30000001',
'dst-address': '0.0.0.0/0',
'gateway': '1.2.3.0',
'gateway-status': '1.2.3.0 reachable via first-ether',
'distance': 1,
'scope': 30,
'target-scope': 10,
'vrf-interface': 'first-ether',
'active': True,
'dynamic': True,
'static': True,
'disabled': False,
},
{
'.id': '*40162F13',
'dst-address': '84.73.216.0/21',
'pref-src': '1.2.3.4',
'gateway': 'first-ether',
'gateway-status': 'first-ether reachable',
'distance': 0,
'scope': 10,
'active': True,
'dynamic': True,
'connect': True,
'disabled': False,
},
{
'.id': '*4016AA23',
'dst-address': '192.168.2.0/24',
'pref-src': '192.168.2.1',
'gateway': 'fourth-ether',
'gateway-status': 'fourth-ether reachable',
'distance': 0,
'scope': 10,
'active': True,
'dynamic': True,
'connect': True,
'disabled': False,
},
{
'.id': '*40168E05',
'dst-address': '192.168.1.0/24',
'pref-src': '192.168.1.1',
'gateway': 'my-bridge',
'gateway-status': 'my-bridge reachable',
'distance': 0,
'scope': 10,
'active': True,
'dynamic': True,
'connect': True,
'disabled': False,
},
],
('routing', 'ospf', 'instance', ): [
{
'.id': '*0',
'name': 'default',
'router-id': '0.0.0.0',
'distribute-default': 'never',
'redistribute-connected': False,
'redistribute-static': False,
'redistribute-rip': False,
'redistribute-bgp': False,
'redistribute-other-ospf': False,
'metric-default': 1,
'metric-connected': 20,
'metric-static': 20,
'metric-rip': 20,
'metric-bgp': 'auto',
'metric-other-ospf': 'auto',
'in-filter': 'ospf-in',
'out-filter': 'ospf-out',
'state': 'down',
'default': True,
'disabled': False,
},
],
('routing', 'ospf', 'neighbor', ): [],
}
class TestRouterosApiFactsModule(ModuleTestCase):
def setUp(self):
super(TestRouterosApiFactsModule, self).setUp()
self.module = api_facts
self.module.LibRouterosError = FakeLibRouterosError
self.module.connect = MagicMock(new=fake_ros_api)
self.module.check_has_library = MagicMock()
self.patch_create_api = patch('ansible_collections.community.routeros.plugins.modules.api_facts.create_api', MagicMock(new=fake_ros_api))
self.patch_create_api.start()
self.patch_query_path = patch('ansible_collections.community.routeros.plugins.modules.api_facts.FactsBase.query_path', self.query_path)
self.patch_query_path.start()
self.module.Key = MagicMock(new=Key)
self.config_module_args = {
'username': 'admin',
'password': 'pаss',
'hostname': '127.0.0.1',
}
def tearDown(self):
self.patch_query_path.stop()
self.patch_create_api.stop()
def query_path(self, path):
response = API_RESPONSES.get(tuple(path))
if response is None:
raise Exception('Unexpected command: %s' % repr(path))
return response
def test_module_fail_when_required_args_missing(self):
with self.assertRaises(AnsibleFailJson) as exc:
with set_module_args({}):
self.module.main()
result = exc.exception.args[0]
self.assertEqual(result['failed'], True)
def test_module_fail_when_invalid_gather_subset(self):
with self.assertRaises(AnsibleFailJson) as exc:
module_args = self.config_module_args.copy()
module_args['gather_subset'] = ['!foobar']
with set_module_args(module_args):
self.module.main()
result = exc.exception.args[0]
self.assertEqual(result['failed'], True)
self.assertEqual(result['msg'], 'Bad subset: foobar')
def test_full_run(self):
with self.assertRaises(AnsibleExitJson) as exc:
with set_module_args(self.config_module_args.copy()):
self.module.main()
result = exc.exception.args[0]
self.assertEqual(result['changed'], False)
self.assertEqual(result['ansible_facts']['ansible_net_all_ipv4_addresses'], [
'192.168.1.1',
'192.168.2.1',
'1.2.3.4',
])
self.assertEqual(result['ansible_facts']['ansible_net_all_ipv6_addresses'], [
'fe80::1:2:3',
'fe80::1:2:4',
'fe80::1:2:5',
])
self.assertEqual(result['ansible_facts']['ansible_net_arch'], 'mipsbe')
self.assertEqual(result['ansible_facts']['ansible_net_bgp_instance'], {
'default': {
'as': 65530,
'client-to-client-reflection': True,
'default': True,
'disabled': False,
'ignore-as-path-len': False,
'name': 'default',
'out-filter': '',
'redistribute-connected': False,
'redistribute-ospf': False,
'redistribute-other-bgp': False,
'redistribute-rip': False,
'redistribute-static': False,
'router-id': '0.0.0.0',
'routing-table': ''
},
})
self.assertEqual(result['ansible_facts']['ansible_net_bgp_peer'], {})
self.assertEqual(result['ansible_facts']['ansible_net_bgp_vpnv4_route'], {})
self.assertEqual(result['ansible_facts']['ansible_net_cpu_load'], 48)
self.assertEqual(result['ansible_facts']['ansible_net_gather_subset'], [
'default',
'hardware',
'interfaces',
'routing',
])
self.assertEqual(result['ansible_facts']['ansible_net_hostname'], 'MikroTik')
self.assertEqual(result['ansible_facts']['ansible_net_interfaces'], {
'my-bridge': {
'actual-mtu': 1500,
'disabled': False,
'fp-rx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-byte': 1234,
'fp-tx-packet': 1234,
'ipv4': [
{
'address': '192.168.1.1',
'subnet': 24
}
],
'ipv6': [
{
'address': 'fe80::1:2:3',
'subnet': 64
}
],
'l2mtu': 1598,
'last-link-up-time': 'apr/22/2022 07:54:48',
'link-downs': 0,
'mac-address': '00:11:22:33:44:66',
'mtu': 'auto',
'name': 'my-bridge',
'running': True,
'rx-byte': 1234,
'rx-drop': 1234,
'rx-error': 1234,
'rx-packet': 1234,
'tx-byte': 1234,
'tx-drop': 1234,
'tx-error': 1234,
'tx-packet': 1234,
'tx-queue-drop': 1234,
'type': 'bridge'
},
'first-ether': {
'actual-mtu': 1500,
'default-name': 'ether1',
'disabled': False,
'fp-rx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-byte': 1234,
'fp-tx-packet': 1234,
'ipv4': [
{
'address': '1.2.3.4',
'subnet': 21
}
],
'ipv6': [
{
'address': 'fe80::1:2:5',
'subnet': 64
}
],
'l2mtu': 1598,
'last-link-up-time': 'apr/22/2022 07:54:55',
'link-downs': 0,
'mac-address': '00:11:22:33:44:55',
'max-l2mtu': 4074,
'mtu': 1500,
'name': 'first-ether',
'running': True,
'rx-byte': 1234,
'rx-drop': 1234,
'rx-error': 1234,
'rx-packet': 1234,
'tx-byte': 1234,
'tx-drop': 1234,
'tx-error': 1234,
'tx-packet': 1234,
'tx-queue-drop': 1234,
'type': 'ether'
},
'second-ether': {
'actual-mtu': 1500,
'default-name': 'ether2',
'disabled': False,
'fp-rx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-byte': 1234,
'fp-tx-packet': 1234,
'l2mtu': 1598,
'last-link-up-time': 'apr/22/2022 07:54:55',
'link-downs': 0,
'mac-address': '00:11:22:33:44:66',
'max-l2mtu': 4074,
'mtu': 1500,
'name': 'second-ether',
'running': True,
'rx-byte': 1234,
'rx-drop': 1234,
'rx-error': 1234,
'rx-packet': 1234,
'slave': True,
'tx-byte': 1234,
'tx-drop': 1234,
'tx-error': 1234,
'tx-packet': 1234,
'tx-queue-drop': 1234,
'type': 'ether'
},
'third-ether': {
'actual-mtu': 1500,
'default-name': 'ether3',
'disabled': False,
'fp-rx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-byte': 1234,
'fp-tx-packet': 1234,
'l2mtu': 1598,
'last-link-up-time': 'apr/22/2022 07:54:55',
'link-downs': 0,
'mac-address': '00:11:22:33:44:77',
'max-l2mtu': 4074,
'mtu': 1500,
'name': 'third-ether',
'running': True,
'rx-byte': 1234,
'rx-drop': 1234,
'rx-error': 1234,
'rx-packet': 1234,
'slave': True,
'tx-byte': 1234,
'tx-drop': 1234,
'tx-error': 1234,
'tx-packet': 1234,
'tx-queue-drop': 1234,
'type': 'ether'
},
'fourth-ether': {
'actual-mtu': 1500,
'default-name': 'ether4',
'disabled': False,
'fp-rx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-byte': 1234,
'fp-tx-packet': 1234,
'ipv4': [
{
'address': '192.168.2.1',
'subnet': 24
}
],
'ipv6': [
{
'address': 'fe80::1:2:4',
'subnet': 64
}
],
'l2mtu': 1598,
'last-link-down-time': 'apr/23/2022 08:22:50',
'last-link-up-time': 'apr/23/2022 08:22:52',
'link-downs': 2,
'mac-address': '00:11:22:33:44:88',
'max-l2mtu': 4074,
'mtu': 1500,
'name': 'fourth-ether',
'running': True,
'rx-byte': 1234,
'rx-drop': 1234,
'rx-error': 1234,
'rx-packet': 1234,
'tx-byte': 1234,
'tx-drop': 1234,
'tx-error': 1234,
'tx-packet': 1234,
'tx-queue-drop': 1234,
'type': 'ether'
},
'fifth-ether': {
'actual-mtu': 1500,
'default-name': 'ether5',
'disabled': False,
'fp-rx-byte': 1234,
'fp-rx-packet': 1234,
'fp-tx-byte': 1234,
'fp-tx-packet': 1234,
'l2mtu': 1598,
'last-link-down-time': 'may/02/2022 18:12:32',
'last-link-up-time': 'may/02/2022 18:08:01',
'link-downs': 14,
'mac-address': '00:11:22:33:44:99',
'max-l2mtu': 4074,
'mtu': 1500,
'name': 'fifth-ether',
'running': False,
'rx-byte': 1234,
'rx-drop': 1234,
'rx-error': 1234,
'rx-packet': 1234,
'slave': True,
'tx-byte': 1234,
'tx-drop': 1234,
'tx-error': 1234,
'tx-packet': 1234,
'tx-queue-drop': 1234,
'type': 'ether'
}
})
self.assertEqual(result['ansible_facts']['ansible_net_memfree_mb'], 12345678 / 1048576.0)
self.assertEqual(result['ansible_facts']['ansible_net_memtotal_mb'], 23456789 / 1048576.0)
self.assertEqual(result['ansible_facts']['ansible_net_model'], '750GL')
self.assertEqual(result['ansible_facts']['ansible_net_neighbors'], [])
self.assertEqual(result['ansible_facts']['ansible_net_ospf_instance'], {
'default': {
'default': True,
'disabled': False,
'distribute-default': 'never',
'in-filter': 'ospf-in',
'metric-bgp': 'auto',
'metric-connected': 20,
'metric-default': 1,
'metric-other-ospf': 'auto',
'metric-rip': 20,
'metric-static': 20,
'name': 'default',
'out-filter': 'ospf-out',
'redistribute-bgp': False,
'redistribute-connected': False,
'redistribute-other-ospf': False,
'redistribute-rip': False,
'redistribute-static': False,
'router-id': '0.0.0.0',
'state': 'down'
}
})
self.assertEqual(result['ansible_facts']['ansible_net_ospf_neighbor'], {})
self.assertEqual(result['ansible_facts']['ansible_net_route'], {
'main': {
'active': True,
'connect': True,
'disabled': False,
'distance': 0,
'dst-address': '192.168.1.0/24',
'dynamic': True,
'gateway': 'my-bridge',
'gateway-status': 'my-bridge reachable',
'pref-src': '192.168.1.1',
'scope': 10
}
})
self.assertEqual(result['ansible_facts']['ansible_net_serialnum'], '0123456789AB')
self.assertEqual(result['ansible_facts']['ansible_net_spacefree_mb'], 123456789 / 1048576.0)
self.assertEqual(result['ansible_facts']['ansible_net_spacetotal_mb'], 234567890 / 1048576.0)
self.assertEqual(result['ansible_facts']['ansible_net_uptime'], '2w3d4h5m6s')
self.assertEqual(result['ansible_facts']['ansible_net_version'], '6.49.6 (stable)')