diff --git a/changelogs/fragments/60980-netapp-facts.yml b/changelogs/fragments/60980-netapp-facts.yml new file mode 100644 index 00000000000..b0511864603 --- /dev/null +++ b/changelogs/fragments/60980-netapp-facts.yml @@ -0,0 +1,2 @@ +minor_changes: +- The ``na_ontap_gather_facts`` module has been deprecated. Use ``na_ontap_info`` instead. diff --git a/docs/docsite/rst/porting_guides/porting_guide_2.9.rst b/docs/docsite/rst/porting_guides/porting_guide_2.9.rst index 6078a8200bb..a1928057007 100644 --- a/docs/docsite/rst/porting_guides/porting_guide_2.9.rst +++ b/docs/docsite/rst/porting_guides/porting_guide_2.9.rst @@ -80,6 +80,8 @@ The following modules will be removed in Ansible 2.13. Please update update your * lambda_facts use :ref:`lambda_info ` instead. +* na_ontap_gather_facts use :ref:`na_ontap_info ` instead. + * nginx_status_facts use :ref:`nginx_status_info ` instead. * nxos_interface use :ref:`nxos_interfaces ` instead. diff --git a/lib/ansible/modules/storage/netapp/na_ontap_gather_facts.py b/lib/ansible/modules/storage/netapp/_na_ontap_gather_facts.py similarity index 99% rename from lib/ansible/modules/storage/netapp/na_ontap_gather_facts.py rename to lib/ansible/modules/storage/netapp/_na_ontap_gather_facts.py index 80e2eb6d480..d88b7ce98f7 100644 --- a/lib/ansible/modules/storage/netapp/na_ontap_gather_facts.py +++ b/lib/ansible/modules/storage/netapp/_na_ontap_gather_facts.py @@ -8,11 +8,15 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], + 'status': ['deprecated'], 'supported_by': 'certified'} DOCUMENTATION = ''' module: na_ontap_gather_facts +deprecated: + removed_in: '2.13' + why: Deprecated in favour of C(_info) module. + alternative: Use M(na_ontap_info) instead. author: Piotr Olczak (@dprts) extends_documentation_fragment: - netapp.na_ontap diff --git a/lib/ansible/modules/storage/netapp/na_ontap_info.py b/lib/ansible/modules/storage/netapp/na_ontap_info.py new file mode 100644 index 00000000000..7119fe7d373 --- /dev/null +++ b/lib/ansible/modules/storage/netapp/na_ontap_info.py @@ -0,0 +1,619 @@ +#!/usr/bin/python + +# (c) 2018 Piotr Olczak +# (c) 2018-2019, NetApp, Inc +# 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 + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + +DOCUMENTATION = ''' +module: na_ontap_info +author: Piotr Olczak (@dprts) +extends_documentation_fragment: + - netapp.na_ontap +short_description: NetApp information gatherer +description: + - This module allows you to gather various information about ONTAP configuration +version_added: "2.9" +requirements: + - netapp_lib +options: + state: + type: str + description: + - Returns "info" + default: "info" + choices: ['info'] + gather_subset: + type: list + description: + - When supplied, this argument will restrict the information collected + to a given subset. Possible values for this argument include + "aggregate_info", "cluster_node_info", "igroup_info", "lun_info", "net_dns_info", + "net_ifgrp_info", + "net_interface_info", "net_port_info", "nvme_info", "nvme_interface_info", + "nvme_namespace_info", "nvme_subsystem_info", "ontap_version", + "qos_adaptive_policy_info", "qos_policy_info", "security_key_manager_key_info", + "security_login_account_info", "storage_failover_info", "volume_info", + "vserver_info", "vserver_login_banner_info", "vserver_motd_info", "vserver_nfs_info" + Can specify a list of values to include a larger subset. Values can also be used + with an initial C(M(!)) to specify that a specific subset should + not be collected. + - nvme is supported with ONTAP 9.4 onwards. + - use "help" to get a list of supported information for your system. + default: "all" +''' + +EXAMPLES = ''' +- name: Get NetApp info (Password Authentication) + na_ontap_info: + state: info + hostname: "na-vsim" + username: "admin" + password: "admins_password" + register: ontap_info +- debug: + msg: "{{ ontap_info.ontap_info }}" + +- name: Limit Info Gathering to Aggregate Information + na_ontap_info: + state: info + hostname: "na-vsim" + username: "admin" + password: "admins_password" + gather_subset: "aggregate_info" + register: ontap_info + +- name: Limit Info Gathering to Volume and Lun Information + na_ontap_info: + state: info + hostname: "na-vsim" + username: "admin" + password: "admins_password" + gather_subset: + - volume_info + - lun_info + register: ontap_info + +- name: Gather all info except for volume and lun information + na_ontap_info: + state: info + hostname: "na-vsim" + username: "admin" + password: "admins_password" + gather_subset: + - "!volume_info" + - "!lun_info" + register: ontap_info +''' + +RETURN = ''' +ontap_info: + description: Returns various information about NetApp cluster configuration + returned: always + type: dict + sample: '{ + "ontap_info": { + "aggregate_info": {...}, + "cluster_node_info": {...}, + "net_dns_info": {...}, + "net_ifgrp_info": {...}, + "net_interface_info": {...}, + "net_port_info": {...}, + "security_key_manager_key_info": {...}, + "security_login_account_info": {...}, + "volume_info": {...}, + "lun_info": {...}, + "storage_failover_info": {...}, + "vserver_login_banner_info": {...}, + "vserver_motd_info": {...}, + "vserver_info": {...}, + "vserver_nfs_info": {...}, + "ontap_version": {...}, + "igroup_info": {...}, + "qos_policy_info": {...}, + "qos_adaptive_policy_info": {...} + }' +''' + +import traceback +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +import ansible.module_utils.netapp as netapp_utils + +try: + import xmltodict + HAS_XMLTODICT = True +except ImportError: + HAS_XMLTODICT = False + +try: + import json + HAS_JSON = True +except ImportError: + HAS_JSON = False + +HAS_NETAPP_LIB = netapp_utils.has_netapp_lib() + + +class NetAppONTAPGatherInfo(object): + '''Class with gather info methods''' + + def __init__(self, module): + self.module = module + self.netapp_info = dict() + + # thanks to coreywan (https://github.com/ansible/ansible/pull/47016) + # for starting this + # min_version identifies the ontapi version which supports this ZAPI + # use 0 if it is supported since 9.1 + self.info_subsets = { + 'net_dns_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'net-dns-get-iter', + 'attribute': 'net-dns-info', + 'field': 'vserver-name', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'net_interface_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'net-interface-get-iter', + 'attribute': 'net-interface-info', + 'field': 'interface-name', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'net_port_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'net-port-get-iter', + 'attribute': 'net-port-info', + 'field': ('node', 'port'), + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'cluster_node_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'cluster-node-get-iter', + 'attribute': 'cluster-node-info', + 'field': 'node-name', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'security_login_account_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'security-login-get-iter', + 'attribute': 'security-login-account-info', + 'field': ('vserver', 'user-name', 'application', 'authentication-method'), + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'aggregate_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'aggr-get-iter', + 'attribute': 'aggr-attributes', + 'field': 'aggregate-name', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'volume_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'volume-get-iter', + 'attribute': 'volume-attributes', + 'field': ('name', 'owning-vserver-name'), + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'lun_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'lun-get-iter', + 'attribute': 'lun-info', + 'field': 'path', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'storage_failover_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'cf-get-iter', + 'attribute': 'storage-failover-info', + 'field': 'node', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'vserver_motd_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'vserver-motd-get-iter', + 'attribute': 'vserver-motd-info', + 'field': 'vserver', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'vserver_login_banner_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'vserver-login-banner-get-iter', + 'attribute': 'vserver-login-banner-info', + 'field': 'vserver', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'security_key_manager_key_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'security-key-manager-key-get-iter', + 'attribute': 'security-key-manager-key-info', + 'field': ('node', 'key-id'), + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'vserver_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'vserver-get-iter', + 'attribute': 'vserver-info', + 'field': 'vserver-name', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'vserver_nfs_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'nfs-service-get-iter', + 'attribute': 'nfs-info', + 'field': 'vserver', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'net_ifgrp_info': { + 'method': self.get_ifgrp_info, + 'kwargs': {}, + 'min_version': '0', + }, + 'ontap_version': { + 'method': self.ontapi, + 'kwargs': {}, + 'min_version': '0', + }, + 'system_node_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'system-node-get-iter', + 'attribute': 'node-details-info', + 'field': 'node', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'igroup_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'igroup-get-iter', + 'attribute': 'initiator-group-info', + 'field': ('vserver', 'initiator-group-name'), + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + 'qos_policy_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'qos-policy-group-get-iter', + 'attribute': 'qos-policy-group-info', + 'field': 'policy-group', + 'query': {'max-records': '1024'}, + }, + 'min_version': '0', + }, + # supported in ONTAP 9.3 and onwards + 'qos_adaptive_policy_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'qos-adaptive-policy-group-get-iter', + 'attribute': 'qos-adaptive-policy-group-info', + 'field': 'policy-group', + 'query': {'max-records': '1024'}, + }, + 'min_version': '130', + }, + # supported in ONTAP 9.4 and onwards + 'nvme_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'nvme-get-iter', + 'attribute': 'nvme-target-service-info', + 'field': 'vserver', + 'query': {'max-records': '1024'}, + }, + 'min_version': '140', + }, + 'nvme_interface_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'nvme-interface-get-iter', + 'attribute': 'nvme-interface-info', + 'field': 'vserver', + 'query': {'max-records': '1024'}, + }, + 'min_version': '140', + }, + 'nvme_subsystem_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'nvme-subsystem-get-iter', + 'attribute': 'nvme-subsystem-info', + 'field': 'subsystem', + 'query': {'max-records': '1024'}, + }, + 'min_version': '140', + }, + 'nvme_namespace_info': { + 'method': self.get_generic_get_iter, + 'kwargs': { + 'call': 'nvme-namespace-get-iter', + 'attribute': 'nvme-namespace-info', + 'field': 'path', + 'query': {'max-records': '1024'}, + }, + 'min_version': '140', + }, + } + + if HAS_NETAPP_LIB is False: + self.module.fail_json(msg="the python NetApp-Lib module is required") + else: + self.server = netapp_utils.setup_na_ontap_zapi(module=self.module) + + def ontapi(self): + '''Method to get ontapi version''' + + api = 'system-get-ontapi-version' + api_call = netapp_utils.zapi.NaElement(api) + try: + results = self.server.invoke_successfully(api_call, enable_tunneling=False) + ontapi_version = results.get_child_content('minor-version') + return ontapi_version if ontapi_version is not None else '0' + except netapp_utils.zapi.NaApiError as error: + self.module.fail_json(msg="Error calling API %s: %s" % + (api, to_native(error)), exception=traceback.format_exc()) + + def call_api(self, call, query=None): + '''Main method to run an API call''' + + api_call = netapp_utils.zapi.NaElement(call) + result = None + + if query: + for key, val in query.items(): + # Can val be nested? + api_call.add_new_child(key, val) + try: + result = self.server.invoke_successfully(api_call, enable_tunneling=False) + return result + except netapp_utils.zapi.NaApiError as error: + if call in ['security-key-manager-key-get-iter']: + return result + else: + self.module.fail_json(msg="Error calling API %s: %s" + % (call, to_native(error)), exception=traceback.format_exc()) + + def get_ifgrp_info(self): + '''Method to get network port ifgroups info''' + + try: + net_port_info = self.netapp_info['net_port_info'] + except KeyError: + net_port_info_calls = self.info_subsets['net_port_info'] + net_port_info = net_port_info_calls['method'](**net_port_info_calls['kwargs']) + interfaces = net_port_info.keys() + + ifgrps = [] + for ifn in interfaces: + if net_port_info[ifn]['port_type'] == 'if_group': + ifgrps.append(ifn) + + net_ifgrp_info = dict() + for ifgrp in ifgrps: + query = dict() + query['node'], query['ifgrp-name'] = ifgrp.split(':') + + tmp = self.get_generic_get_iter('net-port-ifgrp-get', field=('node', 'ifgrp-name'), + attribute='net-ifgrp-info', query=query) + net_ifgrp_info = net_ifgrp_info.copy() + net_ifgrp_info.update(tmp) + return net_ifgrp_info + + def get_generic_get_iter(self, call, attribute=None, field=None, query=None): + '''Method to run a generic get-iter call''' + + generic_call = self.call_api(call, query) + + if call == 'net-port-ifgrp-get': + children = 'attributes' + else: + children = 'attributes-list' + + if generic_call is None: + return None + + if field is None: + out = [] + else: + out = {} + + attributes_list = generic_call.get_child_by_name(children) + + if attributes_list is None: + return None + + for child in attributes_list.get_children(): + dic = xmltodict.parse(child.to_string(), xml_attribs=False) + + if attribute is not None: + dic = dic[attribute] + + if isinstance(field, str): + unique_key = _finditem(dic, field) + out = out.copy() + out.update({unique_key: convert_keys(json.loads(json.dumps(dic)))}) + elif isinstance(field, tuple): + unique_key = ':'.join([_finditem(dic, el) for el in field]) + out = out.copy() + out.update({unique_key: convert_keys(json.loads(json.dumps(dic)))}) + else: + out.append(convert_keys(json.loads(json.dumps(dic)))) + + return out + + def get_all(self, gather_subset): + '''Method to get all subsets''' + + results = netapp_utils.get_cserver(self.server) + cserver = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=results) + netapp_utils.ems_log_event("na_ontap_info", cserver) + + self.netapp_info['ontap_version'] = self.ontapi() + + run_subset = self.get_subset(gather_subset, self.netapp_info['ontap_version']) + if 'help' in gather_subset: + self.netapp_info['help'] = sorted(run_subset) + else: + for subset in run_subset: + call = self.info_subsets[subset] + self.netapp_info[subset] = call['method'](**call['kwargs']) + + return self.netapp_info + + def get_subset(self, gather_subset, version): + '''Method to get a single subset''' + + runable_subsets = set() + exclude_subsets = set() + usable_subsets = [key for key in self.info_subsets.keys() if version >= self.info_subsets[key]['min_version']] + if 'help' in gather_subset: + return usable_subsets + for subset in gather_subset: + if subset == 'all': + runable_subsets.update(usable_subsets) + return runable_subsets + if subset.startswith('!'): + subset = subset[1:] + if subset == 'all': + return set() + exclude = True + else: + exclude = False + + if subset not in usable_subsets: + if subset not in self.info_subsets.keys(): + self.module.fail_json(msg='Bad subset: %s' % subset) + self.module.fail_json(msg='Remote system at version %s does not support %s' % + (version, subset)) + + if exclude: + exclude_subsets.add(subset) + else: + runable_subsets.add(subset) + + if not runable_subsets: + runable_subsets.update(usable_subsets) + + runable_subsets.difference_update(exclude_subsets) + + return runable_subsets + + +# https://stackoverflow.com/questions/14962485/finding-a-key-recursively-in-a-dictionary +def __finditem(obj, key): + + if key in obj: + return obj[key] + for dummy, val in obj.items(): + if isinstance(val, dict): + item = __finditem(val, key) + if item is not None: + return item + return None + + +def _finditem(obj, key): + + value = __finditem(obj, key) + if value is not None: + return value + raise KeyError(key) + + +def convert_keys(d_param): + '''Method to convert hyphen to underscore''' + + out = {} + if isinstance(d_param, dict): + for key, val in d_param.items(): + val = convert_keys(val) + out[key.replace('-', '_')] = val + else: + return d_param + return out + + +def main(): + '''Execute action''' + + argument_spec = netapp_utils.na_ontap_host_argument_spec() + argument_spec.update(dict( + state=dict(type='str', default='info', choices=['info']), + gather_subset=dict(default=['all'], type='list'), + )) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True + ) + + if not HAS_XMLTODICT: + module.fail_json(msg="xmltodict missing") + + if not HAS_JSON: + module.fail_json(msg="json missing") + + state = module.params['state'] + gather_subset = module.params['gather_subset'] + if gather_subset is None: + gather_subset = ['all'] + gf_obj = NetAppONTAPGatherInfo(module) + gf_all = gf_obj.get_all(gather_subset) + result = {'state': state, 'changed': False} + module.exit_json(ontap_info=gf_all, **result) + + +if __name__ == '__main__': + main() diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index e5278d72e00..548b5c327f3 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -5562,8 +5562,8 @@ lib/ansible/modules/storage/netapp/na_ontap_fcp.py validate-modules:E338 lib/ansible/modules/storage/netapp/na_ontap_firewall_policy.py validate-modules:E337 lib/ansible/modules/storage/netapp/na_ontap_firewall_policy.py validate-modules:E338 lib/ansible/modules/storage/netapp/na_ontap_flexcache.py validate-modules:E337 -lib/ansible/modules/storage/netapp/na_ontap_gather_facts.py validate-modules:E337 -lib/ansible/modules/storage/netapp/na_ontap_gather_facts.py validate-modules:E338 +lib/ansible/modules/storage/netapp/_na_ontap_gather_facts.py validate-modules:E337 +lib/ansible/modules/storage/netapp/_na_ontap_gather_facts.py validate-modules:E338 lib/ansible/modules/storage/netapp/na_ontap_igroup.py validate-modules:E337 lib/ansible/modules/storage/netapp/na_ontap_igroup.py validate-modules:E338 lib/ansible/modules/storage/netapp/na_ontap_igroup_initiator.py validate-modules:E337 @@ -6717,8 +6717,8 @@ test/units/modules/storage/netapp/test_na_ontap_firewall_policy.py future-import test/units/modules/storage/netapp/test_na_ontap_firewall_policy.py metaclass-boilerplate test/units/modules/storage/netapp/test_na_ontap_flexcache.py future-import-boilerplate test/units/modules/storage/netapp/test_na_ontap_flexcache.py metaclass-boilerplate -test/units/modules/storage/netapp/test_na_ontap_gather_facts.py future-import-boilerplate -test/units/modules/storage/netapp/test_na_ontap_gather_facts.py metaclass-boilerplate +test/units/modules/storage/netapp/test_na_ontap_info.py future-import-boilerplate +test/units/modules/storage/netapp/test_na_ontap_info.py metaclass-boilerplate test/units/modules/storage/netapp/test_na_ontap_igroup.py future-import-boilerplate test/units/modules/storage/netapp/test_na_ontap_igroup.py metaclass-boilerplate test/units/modules/storage/netapp/test_na_ontap_igroup_initiator.py future-import-boilerplate diff --git a/test/units/modules/storage/netapp/test_na_ontap_gather_facts.py b/test/units/modules/storage/netapp/test_na_ontap_info.py similarity index 83% rename from test/units/modules/storage/netapp/test_na_ontap_gather_facts.py rename to test/units/modules/storage/netapp/test_na_ontap_info.py index 30028486a4c..389e2128b7b 100644 --- a/test/units/modules/storage/netapp/test_na_ontap_gather_facts.py +++ b/test/units/modules/storage/netapp/test_na_ontap_info.py @@ -1,7 +1,7 @@ # (c) 2018-2019, NetApp, Inc # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -''' unit tests for ONTAP Ansible module na_ontap_gather_facts ''' +''' unit tests for ONTAP Ansible module na_ontap_info ''' from __future__ import print_function import json @@ -14,10 +14,10 @@ from ansible.module_utils import basic from ansible.module_utils._text import to_bytes import ansible.module_utils.netapp as netapp_utils -from ansible.modules.storage.netapp.na_ontap_gather_facts import main as gather_facts_main -from ansible.modules.storage.netapp.na_ontap_gather_facts import __finditem as gather_facts_finditem -from ansible.modules.storage.netapp.na_ontap_gather_facts \ - import NetAppONTAPGatherFacts as gather_facts_module # module under test +from ansible.modules.storage.netapp.na_ontap_info import main as info_main +from ansible.modules.storage.netapp.na_ontap_info import __finditem as info_finditem +from ansible.modules.storage.netapp.na_ontap_info \ + import NetAppONTAPGatherInfo as info_module # module under test if not netapp_utils.has_netapp_lib(): pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') @@ -119,15 +119,15 @@ class TestMyModule(unittest.TestCase): 'password': 'password', } - def get_gather_facts_mock_object(self, kind=None): + def get_info_mock_object(self, kind=None): """ - Helper method to return an na_ontap_gather_facts object + Helper method to return an na_ontap_info object """ module = basic.AnsibleModule( argument_spec=netapp_utils.na_ontap_host_argument_spec(), supports_check_mode=True ) - obj = gather_facts_module(module) + obj = info_module(module) obj.netapp_info = dict() if kind is None: obj.server = MockONTAPConnection() @@ -139,14 +139,14 @@ class TestMyModule(unittest.TestCase): ''' required arguments are reported as errors ''' with pytest.raises(AnsibleFailJson) as exc: set_module_args({}) - self.get_gather_facts_mock_object() + self.get_info_mock_object() print('Info: %s' % exc.value.args[0]['msg']) @patch('ansible.module_utils.netapp.ems_log_event') def test_ensure_command_called(self, mock_ems_log): ''' calling get_all will raise a KeyError exception ''' set_module_args(self.mock_args()) - my_obj = self.get_gather_facts_mock_object('vserver') + my_obj = self.get_info_mock_object('vserver') with pytest.raises(KeyError) as exc: my_obj.get_all(['net_interface_info']) if sys.version_info >= (2, 7): @@ -157,7 +157,7 @@ class TestMyModule(unittest.TestCase): def test_get_generic_get_iter(self, mock_ems_log): '''calling get_generic_get_iter will return expected dict''' set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('net_port') + obj = self.get_info_mock_object('net_port') result = obj.get_generic_get_iter( 'net-port-get-iter', attribute='net-port-info', @@ -167,7 +167,7 @@ class TestMyModule(unittest.TestCase): assert result.get('node_0:port_0') assert result.get('node_1:port_1') - @patch('ansible.modules.storage.netapp.na_ontap_gather_facts.NetAppONTAPGatherFacts.get_all') + @patch('ansible.modules.storage.netapp.na_ontap_info.NetAppONTAPGatherInfo.get_all') def test_main(self, get_all): '''test main method.''' set_module_args(self.mock_args()) @@ -176,17 +176,17 @@ class TestMyModule(unittest.TestCase): {'vserver_login_banner_info': 'test_vserver_login_banner_info', 'vserver_info': 'test_vserver_info'}} ] with pytest.raises(AnsibleExitJson) as exc: - gather_facts_main() + info_main() assert exc.value.args[0]['state'] == 'info' - @patch('ansible.modules.storage.netapp.na_ontap_gather_facts.NetAppONTAPGatherFacts.get_generic_get_iter') + @patch('ansible.modules.storage.netapp.na_ontap_info.NetAppONTAPGatherInfo.get_generic_get_iter') def test_get_ifgrp_info(self, get_generic_get_iter): '''test get_ifgrp_info with empty ifgrp_info''' set_module_args(self.mock_args()) get_generic_get_iter.side_effect = [ {} ] - obj = self.get_gather_facts_mock_object() + obj = self.get_info_mock_object() obj.netapp_info['net_port_info'] = {} result = obj.get_ifgrp_info() assert result == {} @@ -194,7 +194,7 @@ class TestMyModule(unittest.TestCase): def test_ontapi_error(self): '''test ontapi will raise zapi error''' set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('zapi_error') + obj = self.get_info_mock_object('zapi_error') with pytest.raises(AnsibleFailJson) as exc: obj.ontapi() assert exc.value.args[0]['msg'] == 'Error calling API system-get-ontapi-version: NetApp API failed. Reason - test:error' @@ -202,7 +202,7 @@ class TestMyModule(unittest.TestCase): def test_call_api_error(self): '''test call_api will raise zapi error''' set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('zapi_error') + obj = self.get_info_mock_object('zapi_error') with pytest.raises(AnsibleFailJson) as exc: obj.call_api('nvme-get-iter') assert exc.value.args[0]['msg'] == 'Error calling API nvme-get-iter: NetApp API failed. Reason - test:error' @@ -211,33 +211,33 @@ class TestMyModule(unittest.TestCase): '''test __find_item return expected key value''' obj = {"A": 1, "B": {"C": {"D": 2}}} key = "D" - result = gather_facts_finditem(obj, key) + result = info_finditem(obj, key) assert result == 2 def test_subset_return_all_complete(self): ''' Check all returns all of the entries if version is high enough ''' version = '140' # change this if new ZAPIs are supported set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') subset = obj.get_subset(['all'], version) - assert set(obj.fact_subsets.keys()) == subset + assert set(obj.info_subsets.keys()) == subset def test_subset_return_all_partial(self): ''' Check all returns a subset of the entries if version is low enough ''' version = '120' # low enough so that some ZAPIs are not supported set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') subset = obj.get_subset(['all'], version) - all_keys = obj.fact_subsets.keys() + all_keys = obj.info_subsets.keys() assert set(all_keys) > subset - supported_keys = filter(lambda key: obj.fact_subsets[key]['min_version'] <= version, all_keys) + supported_keys = filter(lambda key: obj.info_subsets[key]['min_version'] <= version, all_keys) assert set(supported_keys) == subset def test_subset_return_one(self): ''' Check single entry returns one ''' version = '120' # low enough so that some ZAPIs are not supported set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') subset = obj.get_subset(['net_interface_info'], version) assert len(subset) == 1 @@ -245,7 +245,7 @@ class TestMyModule(unittest.TestCase): ''' Check that more than one entry returns the same number ''' version = '120' # low enough so that some ZAPIs are not supported set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') subset_entries = ['net_interface_info', 'net_port_info'] subset = obj.get_subset(subset_entries, version) assert len(subset) == len(subset_entries) @@ -254,7 +254,7 @@ class TestMyModule(unittest.TestCase): ''' Check that a bad subset entry will error out ''' version = '120' # low enough so that some ZAPIs are not supported set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') with pytest.raises(AnsibleFailJson) as exc: subset = obj.get_subset(['net_interface_info', 'my_invalid_subset'], version) print('Info: %s' % exc.value.args[0]['msg']) @@ -265,7 +265,7 @@ class TestMyModule(unittest.TestCase): version = '120' # low enough so that some ZAPIs are not supported key = 'nvme_info' # only supported starting at 140 set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') with pytest.raises(AnsibleFailJson) as exc: subset = obj.get_subset(['net_interface_info', key], version) print('Info: %s' % exc.value.args[0]['msg']) @@ -276,7 +276,7 @@ class TestMyModule(unittest.TestCase): ''' Check usable subset can be empty ''' version = '!' # lower then 0, so that no ZAPI is supported set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') subset = obj.get_subset(['all'], version) assert len(subset) == 0 @@ -284,28 +284,28 @@ class TestMyModule(unittest.TestCase): ''' Check !x returns all of the entries except x if version is high enough ''' version = '140' # change this if new ZAPIs are supported set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') subset = obj.get_subset(['!net_interface_info'], version) - assert len(obj.fact_subsets.keys()) == len(subset) + 1 + assert len(obj.info_subsets.keys()) == len(subset) + 1 subset.add('net_interface_info') - assert set(obj.fact_subsets.keys()) == subset + assert set(obj.info_subsets.keys()) == subset def test_subset_return_all_expect_three(self): ''' Check !x,!y,!z returns all of the entries except x, y, z if version is high enough ''' version = '140' # change this if new ZAPIs are supported set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') subset = obj.get_subset(['!net_interface_info', '!nvme_info', '!ontap_version'], version) - assert len(obj.fact_subsets.keys()) == len(subset) + 3 + assert len(obj.info_subsets.keys()) == len(subset) + 3 subset.update(['net_interface_info', 'nvme_info', 'ontap_version']) - assert set(obj.fact_subsets.keys()) == subset + assert set(obj.info_subsets.keys()) == subset def test_subset_return_none_with_exclusion(self): ''' Check usable subset can be empty with !x ''' version = '!' # lower then 0, so that no ZAPI is supported key = 'net_interface_info' set_module_args(self.mock_args()) - obj = self.get_gather_facts_mock_object('vserver') + obj = self.get_info_mock_object('vserver') with pytest.raises(AnsibleFailJson) as exc: subset = obj.get_subset(['!' + key], version) print('Info: %s' % exc.value.args[0]['msg'])