diff --git a/lib/ansible/module_utils/network/common/facts/facts.py b/lib/ansible/module_utils/network/common/facts/facts.py index 4faf877e87a..45b130f219b 100644 --- a/lib/ansible/module_utils/network/common/facts/facts.py +++ b/lib/ansible/module_utils/network/common/facts/facts.py @@ -23,7 +23,7 @@ class FactsBase(object): self._connection = get_resource_connection(module) self.ansible_facts = {'ansible_network_resources': {}} - self.ansible_facts['ansible_gather_network_resources'] = list() + self.ansible_facts['ansible_net_gather_network_resources'] = list() self.ansible_facts['ansible_net_gather_subset'] = list() if not self._gather_subset: @@ -65,7 +65,8 @@ class FactsBase(object): exclude = False if subset not in valid_subsets: - self._module.fail_json(msg='Bad subset') + self._module.fail_json(msg='Subset must be one of [%s], got %s' % + (', '.join(sorted([item for item in valid_subsets])), subset)) if exclude: exclude_subsets.add(subset) @@ -75,7 +76,6 @@ class FactsBase(object): if not runable_subsets: runable_subsets.update(valid_subsets) runable_subsets.difference_update(exclude_subsets) - return runable_subsets def get_network_resources_facts(self, net_res_choices, facts_resource_obj_map, resource_facts_type=None, data=None): @@ -95,7 +95,7 @@ class FactsBase(object): restorun_subsets = self.gen_runable(resource_facts_type, frozenset(net_res_choices)) if restorun_subsets: - self.ansible_facts['gather_network_resources'] = list(restorun_subsets) + self.ansible_facts['ansible_net_gather_network_resources'] = list(restorun_subsets) instances = list() for key in restorun_subsets: fact_cls_obj = facts_resource_obj_map.get(key) @@ -112,9 +112,10 @@ class FactsBase(object): legacy_facts_type = self._gather_subset runable_subsets = self.gen_runable(legacy_facts_type, frozenset(fact_legacy_obj_map.keys())) + runable_subsets.add('default') if runable_subsets: facts = dict() - facts['gather_subset'] = list(runable_subsets) + facts['ansible_net_gather_subset'] = list(runable_subsets) instances = list() for key in runable_subsets: diff --git a/lib/ansible/module_utils/network/junos/argspec/__init__.py b/lib/ansible/module_utils/network/junos/argspec/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/network/junos/argspec/facts/__init__.py b/lib/ansible/module_utils/network/junos/argspec/facts/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/network/junos/argspec/facts/facts.py b/lib/ansible/module_utils/network/junos/argspec/facts/facts.py new file mode 100644 index 00000000000..7b0171a6e71 --- /dev/null +++ b/lib/ansible/module_utils/network/junos/argspec/facts/facts.py @@ -0,0 +1,25 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The arg spec for the junos facts module. +""" +CHOICES = [ + 'all', +] + + +class FactsArgs(object): + """ The arg spec for the junos facts module + """ + + def __init__(self, **kwargs): + pass + + argument_spec = { + 'gather_subset': dict(default=['!config'], type='list'), + 'config_format': dict(default='text', choices=['xml', 'text', 'set', 'json']), + 'gather_network_resources': dict(choices=CHOICES, type='list'), + } diff --git a/lib/ansible/module_utils/network/junos/config/__init__.py b/lib/ansible/module_utils/network/junos/config/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/network/junos/facts/__init__.py b/lib/ansible/module_utils/network/junos/facts/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/network/junos/facts/facts.py b/lib/ansible/module_utils/network/junos/facts/facts.py new file mode 100644 index 00000000000..09e90b24aab --- /dev/null +++ b/lib/ansible/module_utils/network/junos/facts/facts.py @@ -0,0 +1,64 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The facts class for junos +this file validates each subset of facts and selectively +calls the appropriate facts gathering function +""" + +from ansible.module_utils.network.junos.argspec.facts.facts import FactsArgs +from ansible.module_utils.network.common.facts.facts import FactsBase +from ansible.module_utils.network.junos.facts.legacy.base import Default, Hardware, Config, Interfaces, OFacts, HAS_PYEZ + +FACT_LEGACY_SUBSETS = dict( + default=Default, + hardware=Hardware, + config=Config, + interfaces=Interfaces, +) +FACT_RESOURCE_SUBSETS = dict( +) + + +class Facts(FactsBase): + """ The fact class for junos + """ + + VALID_LEGACY_GATHER_SUBSETS = frozenset(FACT_LEGACY_SUBSETS.keys()) + VALID_RESOURCE_SUBSETS = frozenset(FACT_RESOURCE_SUBSETS.keys()) + + def __init__(self, module): + super(Facts, self).__init__(module) + + def get_facts(self, legacy_facts_type=None, resource_facts_type=None, data=None): + """ Collect the facts for junos + :param legacy_facts_type: List of legacy facts types + :param resource_facts_type: List of resource fact types + :param data: previously collected conf + :rtype: dict + :return: the facts gathered + """ + netres_choices = FactsArgs.argument_spec['gather_network_resources'].get('choices', []) + if self.VALID_RESOURCE_SUBSETS: + self.get_network_resources_facts(netres_choices, FACT_RESOURCE_SUBSETS, resource_facts_type, data) + + if not legacy_facts_type: + legacy_facts_type = self._gather_subset + # fetch old style facts only when explicitly mentioned in gather_subset option + if 'ofacts' in legacy_facts_type: + if HAS_PYEZ: + self.ansible_facts.update(OFacts(self._module).populate()) + else: + self._warnings.extend([ + 'junos-eznc is required to gather old style facts but does not appear to be installed. ' + 'It can be installed using `pip install junos-eznc`']) + self.ansible_facts['ansible_net_gather_subset'].append('ofacts') + legacy_facts_type.remove('ofacts') + + if self.VALID_LEGACY_GATHER_SUBSETS: + self.get_network_legacy_facts(FACT_LEGACY_SUBSETS, legacy_facts_type) + + return self.ansible_facts, self._warnings diff --git a/lib/ansible/module_utils/network/junos/facts/legacy/__init__.py b/lib/ansible/module_utils/network/junos/facts/legacy/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/network/junos/facts/legacy/base.py b/lib/ansible/module_utils/network/junos/facts/legacy/base.py new file mode 100644 index 00000000000..a4b20ab2457 --- /dev/null +++ b/lib/ansible/module_utils/network/junos/facts/legacy/base.py @@ -0,0 +1,226 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The junos interfaces fact class +It is in this file the configuration is collected from the device +for a given resource, parsed, and the facts tree is populated +based on the configuration. +""" +import platform + +from ansible.module_utils.network.common.netconf import exec_rpc +from ansible.module_utils.network.junos.junos import get_param, tostring +from ansible.module_utils.network.junos.junos import get_configuration, get_capabilities +from ansible.module_utils._text import to_native + + +try: + from lxml.etree import Element, SubElement +except ImportError: + from xml.etree.ElementTree import Element, SubElement + +try: + from jnpr.junos import Device + from jnpr.junos.exception import ConnectError + HAS_PYEZ = True +except ImportError: + HAS_PYEZ = False + + +class FactsBase(object): + + def __init__(self, module): + self.module = module + self.facts = dict() + self.warnings = [] + + def populate(self): + raise NotImplementedError + + def cli(self, command): + reply = command(self.module, command) + output = reply.find('.//output') + if not output: + self.module.fail_json(msg='failed to retrieve facts for command %s' % command) + return str(output.text).strip() + + def rpc(self, rpc): + return exec_rpc(self.module, tostring(Element(rpc))) + + def get_text(self, ele, tag): + try: + return str(ele.find(tag).text).strip() + except AttributeError: + pass + + +class Default(FactsBase): + + def populate(self): + self.facts.update(self.platform_facts()) + + reply = self.rpc('get-chassis-inventory') + data = reply.find('.//chassis-inventory/chassis') + self.facts['serialnum'] = self.get_text(data, 'serial-number') + + def platform_facts(self): + platform_facts = {} + + resp = get_capabilities(self.module) + device_info = resp['device_info'] + + platform_facts['system'] = device_info['network_os'] + + for item in ('model', 'image', 'version', 'platform', 'hostname'): + val = device_info.get('network_os_%s' % item) + if val: + platform_facts[item] = val + + platform_facts['api'] = resp['network_api'] + platform_facts['python_version'] = platform.python_version() + + return platform_facts + + +class Config(FactsBase): + + def populate(self): + config_format = self.module.params['config_format'] + reply = get_configuration(self.module, format=config_format) + + if config_format == 'xml': + config = tostring(reply.find('configuration')).strip() + + elif config_format == 'text': + config = self.get_text(reply, 'configuration-text') + + elif config_format == 'json': + config = self.module.from_json(reply.text.strip()) + + elif config_format == 'set': + config = self.get_text(reply, 'configuration-set') + + self.facts['config'] = config + + +class Hardware(FactsBase): + + def populate(self): + + reply = self.rpc('get-system-memory-information') + data = reply.find('.//system-memory-information/system-memory-summary-information') + + self.facts.update({ + 'memfree_mb': int(self.get_text(data, 'system-memory-free')), + 'memtotal_mb': int(self.get_text(data, 'system-memory-total')) + }) + + reply = self.rpc('get-system-storage') + data = reply.find('.//system-storage-information') + + filesystems = list() + for obj in data: + filesystems.append(self.get_text(obj, 'filesystem-name')) + self.facts['filesystems'] = filesystems + + reply = self.rpc('get-route-engine-information') + data = reply.find('.//route-engine-information') + + routing_engines = dict() + for obj in data: + slot = self.get_text(obj, 'slot') + routing_engines.update({slot: {}}) + routing_engines[slot].update({'slot': slot}) + for child in obj: + if child.text != "\n": + routing_engines[slot].update({child.tag.replace("-", "_"): child.text}) + + self.facts['routing_engines'] = routing_engines + + if len(data) > 1: + self.facts['has_2RE'] = True + else: + self.facts['has_2RE'] = False + + reply = self.rpc('get-chassis-inventory') + data = reply.findall('.//chassis-module') + + modules = list() + for obj in data: + mod = dict() + for child in obj: + if child.text != "\n": + mod.update({child.tag.replace("-", "_"): child.text}) + modules.append(mod) + + self.facts['modules'] = modules + + +class Interfaces(FactsBase): + + def populate(self): + ele = Element('get-interface-information') + SubElement(ele, 'detail') + reply = exec_rpc(self.module, tostring(ele)) + + interfaces = {} + + for item in reply[0]: + name = self.get_text(item, 'name') + obj = { + 'oper-status': self.get_text(item, 'oper-status'), + 'admin-status': self.get_text(item, 'admin-status'), + 'speed': self.get_text(item, 'speed'), + 'macaddress': self.get_text(item, 'hardware-physical-address'), + 'mtu': self.get_text(item, 'mtu'), + 'type': self.get_text(item, 'if-type'), + } + + interfaces[name] = obj + + self.facts['interfaces'] = interfaces + + +class OFacts(FactsBase): + def _connect(self, module): + host = get_param(module, 'host') + + kwargs = { + 'port': get_param(module, 'port') or 830, + 'user': get_param(module, 'username') + } + + if get_param(module, 'password'): + kwargs['passwd'] = get_param(module, 'password') + + if get_param(module, 'ssh_keyfile'): + kwargs['ssh_private_key_file'] = get_param(module, 'ssh_keyfile') + + kwargs['gather_facts'] = False + try: + device = Device(host, **kwargs) + device.open() + device.timeout = get_param(module, 'timeout') or 10 + except ConnectError as exc: + module.fail_json('unable to connect to %s: %s' % (host, to_native(exc))) + + return device + + def populate(self): + + device = self._connect(self.module) + facts = dict(device.facts) + + if '2RE' in facts: + facts['has_2RE'] = facts['2RE'] + del facts['2RE'] + + facts['version_info'] = dict(facts['version_info']) + if 'junos_info' in facts: + for key, value in facts['junos_info'].items(): + if 'object' in value: + value['object'] = dict(value['object']) + + return facts diff --git a/lib/ansible/module_utils/network/junos/utils/__init__.py b/lib/ansible/module_utils/network/junos/utils/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/network/junos/utils/utils.py b/lib/ansible/module_utils/network/junos/utils/utils.py new file mode 100644 index 00000000000..1c013cf1db5 --- /dev/null +++ b/lib/ansible/module_utils/network/junos/utils/utils.py @@ -0,0 +1,41 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# utils +from ansible.module_utils._text import to_text + +try: + from ncclient.xml_ import to_ele, to_xml, new_ele, sub_ele + HAS_NCCLIENT = True +except (ImportError, AttributeError): + HAS_NCCLIENT = False + + +def build_root_xml_node(tag): + return new_ele(tag) + + +def build_child_xml_node(parent, tag, text=None, attrib=None): + element = sub_ele(parent, tag) + if text: + element.text = to_text(text) + if attrib: + element.attrib.update(attrib) + return element + + +def _handle_field_replace(root, field, have, want, tag=None): + tag = field if not tag else tag + want_value = want.get(field) if want else None + have_value = have.get(field) if have else None + if have_value: + if want_value: + if want_value != have_value: + build_child_xml_node(root, tag, want_value) + else: + build_child_xml_node(root, tag, None, {'delete': 'delete'}) + elif want_value: + build_child_xml_node(root, tag, want_value) diff --git a/lib/ansible/modules/network/junos/junos_facts.py b/lib/ansible/modules/network/junos/junos_facts.py index 161176639bf..e5b08ac5e08 100644 --- a/lib/ansible/modules/network/junos/junos_facts.py +++ b/lib/ansible/modules/network/junos/junos_facts.py @@ -42,7 +42,7 @@ options: junos-eznc library to be installed on control node and the device login credentials must be given in C(provider) option. required: false - default: ['!config', '!ofacts'] + default: ['!config'] version_added: "2.3" config_format: description: @@ -51,11 +51,21 @@ options: only when C(config) value is present in I(gather_subset). The I(config_format) should be supported by the junos version running on device. This value is not applicable while fetching old style facts that is - when C(ofacts) value is present in value if I(gather_subset) value. + when C(ofacts) value is present in value if I(gather_subset) value. This option + is valid only for C(gather_subset) values. required: false default: 'text' choices: ['xml', 'text', 'set', 'json'] version_added: "2.3" + gather_network_resources: + description: + - When supplied, this argument will restrict the facts collected + to a given subset. Possible values for this argument include + all and the resources like interfaces, vlans etc. + Can specify a list of values to include a larger subset. + choices: ['all'] + required: false + version_added: "2.9" requirements: - ncclient (>=v0.5.2) notes: @@ -78,6 +88,11 @@ EXAMPLES = """ - name: collect default set of facts and configuration junos_facts: gather_subset: config + +- name: Gather legacy and resource facts + junos_facts: + gather_subset: all + gather_network_resources: all """ RETURN = """ @@ -86,316 +101,28 @@ ansible_facts: returned: always type: dict """ - -import platform - from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.netconf import exec_rpc -from ansible.module_utils.network.junos.junos import junos_argument_spec, get_param, tostring -from ansible.module_utils.network.junos.junos import get_configuration, get_capabilities -from ansible.module_utils._text import to_native -from ansible.module_utils.six import iteritems - - -try: - from lxml.etree import Element, SubElement -except ImportError: - from xml.etree.ElementTree import Element, SubElement - -try: - from jnpr.junos import Device - from jnpr.junos.exception import ConnectError - HAS_PYEZ = True -except ImportError: - HAS_PYEZ = False - -USE_PERSISTENT_CONNECTION = True - - -class FactsBase(object): - - def __init__(self, module): - self.module = module - self.facts = dict() - - def populate(self): - raise NotImplementedError - - def cli(self, command): - reply = command(self.module, command) - output = reply.find('.//output') - if not output: - self.module.fail_json(msg='failed to retrieve facts for command %s' % command) - return str(output.text).strip() - - def rpc(self, rpc): - return exec_rpc(self.module, tostring(Element(rpc))) - - def get_text(self, ele, tag): - try: - return str(ele.find(tag).text).strip() - except AttributeError: - pass - - -class Default(FactsBase): - - def populate(self): - self.facts.update(self.platform_facts()) - - reply = self.rpc('get-chassis-inventory') - data = reply.find('.//chassis-inventory/chassis') - self.facts['serialnum'] = self.get_text(data, 'serial-number') - - def platform_facts(self): - platform_facts = {} - - resp = get_capabilities(self.module) - device_info = resp['device_info'] - - platform_facts['system'] = device_info['network_os'] - - for item in ('model', 'image', 'version', 'platform', 'hostname'): - val = device_info.get('network_os_%s' % item) - if val: - platform_facts[item] = val - - platform_facts['api'] = resp['network_api'] - platform_facts['python_version'] = platform.python_version() - - return platform_facts - - -class Config(FactsBase): - - def populate(self): - config_format = self.module.params['config_format'] - reply = get_configuration(self.module, format=config_format) - - if config_format == 'xml': - config = tostring(reply.find('configuration')).strip() - - elif config_format == 'text': - config = self.get_text(reply, 'configuration-text') - - elif config_format == 'json': - config = self.module.from_json(reply.text.strip()) - - elif config_format == 'set': - config = self.get_text(reply, 'configuration-set') - - self.facts['config'] = config - - -class Hardware(FactsBase): - - def populate(self): - - reply = self.rpc('get-system-memory-information') - data = reply.find('.//system-memory-information/system-memory-summary-information') - - self.facts.update({ - 'memfree_mb': int(self.get_text(data, 'system-memory-free')), - 'memtotal_mb': int(self.get_text(data, 'system-memory-total')) - }) - - reply = self.rpc('get-system-storage') - data = reply.find('.//system-storage-information') - - filesystems = list() - for obj in data: - filesystems.append(self.get_text(obj, 'filesystem-name')) - self.facts['filesystems'] = filesystems - - reply = self.rpc('get-route-engine-information') - data = reply.find('.//route-engine-information') - - routing_engines = dict() - for obj in data: - slot = self.get_text(obj, 'slot') - routing_engines.update({slot: {}}) - routing_engines[slot].update({'slot': slot}) - for child in obj: - if child.text != "\n": - routing_engines[slot].update({child.tag.replace("-", "_"): child.text}) - - self.facts['routing_engines'] = routing_engines - - if len(data) > 1: - self.facts['has_2RE'] = True - else: - self.facts['has_2RE'] = False - - reply = self.rpc('get-chassis-inventory') - data = reply.findall('.//chassis-module') - - modules = list() - for obj in data: - mod = dict() - for child in obj: - if child.text != "\n": - mod.update({child.tag.replace("-", "_"): child.text}) - modules.append(mod) - - self.facts['modules'] = modules - - -class Interfaces(FactsBase): - - def populate(self): - ele = Element('get-interface-information') - SubElement(ele, 'detail') - reply = exec_rpc(self.module, tostring(ele)) - - interfaces = {} - - for item in reply[0]: - name = self.get_text(item, 'name') - obj = { - 'oper-status': self.get_text(item, 'oper-status'), - 'admin-status': self.get_text(item, 'admin-status'), - 'speed': self.get_text(item, 'speed'), - 'macaddress': self.get_text(item, 'hardware-physical-address'), - 'mtu': self.get_text(item, 'mtu'), - 'type': self.get_text(item, 'if-type'), - } - - interfaces[name] = obj - - self.facts['interfaces'] = interfaces - - -class OFacts(FactsBase): - def _connect(self, module): - host = get_param(module, 'host') - - kwargs = { - 'port': get_param(module, 'port') or 830, - 'user': get_param(module, 'username') - } - - if get_param(module, 'password'): - kwargs['passwd'] = get_param(module, 'password') - - if get_param(module, 'ssh_keyfile'): - kwargs['ssh_private_key_file'] = get_param(module, 'ssh_keyfile') - - kwargs['gather_facts'] = False - try: - device = Device(host, **kwargs) - device.open() - device.timeout = get_param(module, 'timeout') or 10 - except ConnectError as exc: - module.fail_json('unable to connect to %s: %s' % (host, to_native(exc))) - - return device - - def populate(self): - - device = self._connect(self.module) - facts = dict(device.facts) - - if '2RE' in facts: - facts['has_2RE'] = facts['2RE'] - del facts['2RE'] - - facts['version_info'] = dict(facts['version_info']) - if 'junos_info' in facts: - for key, value in facts['junos_info'].items(): - if 'object' in value: - value['object'] = dict(value['object']) - - return facts - - -FACT_SUBSETS = dict( - default=Default, - hardware=Hardware, - config=Config, - interfaces=Interfaces, - ofacts=OFacts -) - -VALID_SUBSETS = frozenset(FACT_SUBSETS.keys()) +from ansible.module_utils.network.junos.argspec.facts.facts import FactsArgs +from ansible.module_utils.network.junos.facts.facts import Facts +from ansible.module_utils.network.junos.junos import junos_argument_spec def main(): """ Main entry point for AnsibleModule """ - argument_spec = dict( - gather_subset=dict(default=['!config', '!ofacts'], type='list'), - config_format=dict(default='text', choices=['xml', 'text', 'set', 'json']), - ) - + argument_spec = FactsArgs.argument_spec argument_spec.update(junos_argument_spec) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - warnings = list() - gather_subset = module.params['gather_subset'] - - runable_subsets = set() - exclude_subsets = set() - - for subset in gather_subset: - if subset == 'all': - runable_subsets.update(VALID_SUBSETS) - continue - - if subset.startswith('!'): - subset = subset[1:] - if subset == 'all': - exclude_subsets.update(VALID_SUBSETS) - continue - exclude = True - else: - exclude = False - - if subset not in VALID_SUBSETS: - module.fail_json(msg='Subset must be one of [%s], got %s' % - (', '.join(sorted([subset for subset in - VALID_SUBSETS])), subset)) - - if exclude: - exclude_subsets.add(subset) - else: - runable_subsets.add(subset) - - if not runable_subsets: - runable_subsets.update(VALID_SUBSETS) - - runable_subsets.difference_update(exclude_subsets) - runable_subsets.add('default') - - # handle fetching old style facts separately - runable_subsets.discard('ofacts') - - facts = dict() - facts['gather_subset'] = list(runable_subsets) - - instances = list() - ansible_facts = dict() - - # fetch old style facts only when explicitly mentioned in gather_subset option - if 'ofacts' in gather_subset: - if HAS_PYEZ: - ansible_facts.update(OFacts(module).populate()) - else: - warnings += ['junos-eznc is required to gather old style facts but does not appear to be installed. ' - 'It can be installed using `pip install junos-eznc`'] - facts['gather_subset'].append('ofacts') - - for key in runable_subsets: - instances.append(FACT_SUBSETS[key](module)) + warnings = ['default value for `gather_subset` ' + 'will be changed to `min` from `!config` v2.11 onwards'] - for inst in instances: - inst.populate() - facts.update(inst.facts) + result = Facts(module).get_facts() - for key, value in iteritems(facts): - key = 'ansible_net_%s' % key - ansible_facts[key] = value + ansible_facts, additional_warnings = result + warnings.extend(additional_warnings) module.exit_json(ansible_facts=ansible_facts, warnings=warnings) diff --git a/test/units/modules/network/junos/test_junos_facts.py b/test/units/modules/network/junos/test_junos_facts.py index c2ac3589a45..a8b81696256 100644 --- a/test/units/modules/network/junos/test_junos_facts.py +++ b/test/units/modules/network/junos/test_junos_facts.py @@ -46,20 +46,24 @@ class TestJunosCommandModule(TestJunosModule): def setUp(self): super(TestJunosCommandModule, self).setUp() - self.mock_get_config = patch('ansible.modules.network.junos.junos_facts.get_configuration') + self.mock_get_config = patch('ansible.module_utils.network.junos.facts.legacy.base.get_configuration') self.get_config = self.mock_get_config.start() self.mock_netconf = patch('ansible.module_utils.network.junos.junos.NetconfConnection') self.netconf_conn = self.mock_netconf.start() - self.mock_exec_rpc = patch('ansible.modules.network.junos.junos_facts.exec_rpc') + self.mock_exec_rpc = patch('ansible.module_utils.network.junos.facts.legacy.base.exec_rpc') self.exec_rpc = self.mock_exec_rpc.start() self.mock_netconf_rpc = patch('ansible.module_utils.network.common.netconf.NetconfConnection') self.netconf_rpc = self.mock_netconf_rpc.start() - self.mock_get_capabilities = patch('ansible.modules.network.junos.junos_facts.get_capabilities') + self.mock_get_resource_connection = patch('ansible.module_utils.network.common.facts.facts.get_resource_connection') + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_capabilities = patch('ansible.module_utils.network.junos.facts.legacy.base.get_capabilities') self.get_capabilities = self.mock_get_capabilities.start() + self.get_capabilities.return_value = { 'device_info': { 'network_os': 'junos', @@ -76,6 +80,7 @@ class TestJunosCommandModule(TestJunosModule): self.mock_exec_rpc.stop() self.mock_netconf_rpc.stop() self.mock_get_capabilities.stop() + self.mock_get_resource_connection.stop() def load_fixtures(self, commands=None, format='text', changed=False): def load_from_file(*args, **kwargs):