diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index b469a95c9a6..691ec4f616a 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -1929,14 +1929,23 @@ class AnsibleModule(object): self._options_context.append(k) + key = None + for (name, value) in spec.items(): + # specifies how to map a single value to spec + if value.get('key'): + key = name + break + if isinstance(params[k], dict): elements = [params[k]] else: elements = params[k] - for param in elements: + for index, param in enumerate(elements): if not isinstance(param, dict): - self.fail_json(msg="value of %s must be of type dict or list of dict" % k) + if key is None: + self.fail_json(msg="options spec require a key argument to map it to a single value '%s'" % param) + elements[index] = param = {key: param} self._set_fallbacks(spec, param) options_aliases = self._handle_aliases(spec, param) diff --git a/lib/ansible/module_utils/network/common/utils.py b/lib/ansible/module_utils/network/common/utils.py index cf3faaf91be..38d46b683ff 100644 --- a/lib/ansible/module_utils/network/common/utils.py +++ b/lib/ansible/module_utils/network/common/utils.py @@ -65,6 +65,10 @@ def sort_list(val): class Entity(object): """Transforms a dict to with an argument spec + This class has been deprecated as of Ansible 2.5 and will be + removed from the code in future release. + Please use the suboptions in module argument spec instead. + This class will take a dict and apply an Ansible argument spec to the values. The resulting dict will contain all of the keys in the param with appropriate values set. @@ -183,7 +187,12 @@ class Entity(object): class EntityCollection(Entity): - """Extends ```Entity``` to handle a list of dicts """ + """Extends ```Entity``` to handle a list of dicts + + This class has been deprecated as of Ansible 2.5 and will be + removed from the code in future release. + Please use the suboptions in module argument spec instead. + """ def __call__(self, iterable, strict=True): if iterable is None: @@ -198,11 +207,21 @@ class EntityCollection(Entity): # these two are for backwards compatibility and can be removed once all of the # modules that use them are updated class ComplexDict(Entity): + """ + This class has been deprecated as of Ansible 2.5 and will be + removed from the code in future release. + Please use the suboptions in module argument spec instead. + """ def __init__(self, attrs, module, *args, **kwargs): super(ComplexDict, self).__init__(module, attrs, *args, **kwargs) class ComplexList(EntityCollection): + """ + This class has been deprecated as of Ansible 2.5 and will be + removed from the code in future release. + Please use the suboptions in module argument spec instead. + """ def __init__(self, attrs, module, *args, **kwargs): super(ComplexList, self).__init__(module, attrs, *args, **kwargs) diff --git a/lib/ansible/module_utils/network/eos/eos.py b/lib/ansible/module_utils/network/eos/eos.py index a548f139345..3567721ce9d 100644 --- a/lib/ansible/module_utils/network/eos/eos.py +++ b/lib/ansible/module_utils/network/eos/eos.py @@ -33,8 +33,8 @@ import time from ansible.module_utils._text import to_text, to_native from ansible.module_utils.basic import env_fallback, return_values from ansible.module_utils.connection import exec_command -from ansible.module_utils.network.common.utils import to_list, ComplexList -from ansible.module_utils.six import iteritems +from ansible.module_utils.network.common.utils import to_list +from ansible.module_utils.six import iteritems, string_types from ansible.module_utils.urls import fetch_url _DEVICE_CONNECTION = None @@ -150,7 +150,6 @@ class Cli: """Run list of commands on remote device and return results """ responses = list() - for cmd in to_list(commands): rc, out, err = self.exec_command(cmd) out = to_text(out, errors='surrogate_then_replace') @@ -429,22 +428,6 @@ def is_eapi(module): return 'eapi' in (transport, provider_transport) -def to_command(module, commands): - if is_eapi(module): - default_output = 'json' - else: - default_output = 'text' - - transform = ComplexList(dict( - command=dict(key=True), - output=dict(default=default_output), - prompt=dict(), - answer=dict() - ), module) - - return transform(to_list(commands)) - - def get_config(module, flags=None): flags = None if flags is None else flags @@ -454,7 +437,15 @@ def get_config(module, flags=None): def run_commands(module, commands): conn = get_connection(module) - return conn.run_commands(to_command(module, commands)) + if is_eapi(module): + default_output = 'json' + else: + default_output = 'text' + + for index, cmd in enumerate(to_list(commands)): + if isinstance(cmd, string_types): + commands[index] = {'command': cmd, 'output': default_output} + return conn.run_commands(to_list(commands)) def load_config(module, config, commit=False, replace=False): diff --git a/lib/ansible/module_utils/network/ios/ios.py b/lib/ansible/module_utils/network/ios/ios.py index 85ce640093d..e27a62bf2af 100644 --- a/lib/ansible/module_utils/network/ios/ios.py +++ b/lib/ansible/module_utils/network/ios/ios.py @@ -27,8 +27,9 @@ # from ansible.module_utils._text import to_text from ansible.module_utils.basic import env_fallback, return_values -from ansible.module_utils.network.common.utils import to_list, ComplexList from ansible.module_utils.connection import exec_command +from ansible.module_utils.network.common.utils import to_list +from ansible.module_utils.six import string_types _DEVICE_CONFIGS = {} @@ -100,20 +101,12 @@ def get_config(module, flags=None): return cfg -def to_commands(module, commands): - spec = { - 'command': dict(key=True), - 'prompt': dict(), - 'answer': dict() - } - transform = ComplexList(spec, module) - return transform(commands) - - def run_commands(module, commands, check_rc=True): responses = list() - commands = to_commands(module, to_list(commands)) - for cmd in commands: + for cmd in to_list(commands): + if isinstance(cmd, string_types): + cmd = {'command': cmd} + cmd = module.jsonify(cmd) rc, out, err = exec_command(module, cmd) if check_rc and rc != 0: diff --git a/lib/ansible/module_utils/network/iosxr/iosxr.py b/lib/ansible/module_utils/network/iosxr/iosxr.py index 805acf85129..87b72ceffe5 100644 --- a/lib/ansible/module_utils/network/iosxr/iosxr.py +++ b/lib/ansible/module_utils/network/iosxr/iosxr.py @@ -79,12 +79,6 @@ iosxr_argument_spec = { 'provider': dict(type='dict', options=iosxr_provider_spec) } -command_spec = { - 'command': dict(), - 'prompt': dict(default=None), - 'answer': dict(default=None) -} - iosxr_top_spec = { 'host': dict(removed_in_version=2.9), 'port': dict(removed_in_version=2.9, type='int'), diff --git a/lib/ansible/module_utils/network/nxos/nxos.py b/lib/ansible/module_utils/network/nxos/nxos.py index 4eaad230cda..f6dfd9381e8 100644 --- a/lib/ansible/module_utils/network/nxos/nxos.py +++ b/lib/ansible/module_utils/network/nxos/nxos.py @@ -32,7 +32,7 @@ import collections from ansible.module_utils._text import to_text from ansible.module_utils.basic import env_fallback, return_values -from ansible.module_utils.network.common.utils import to_list, ComplexList +from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.connection import exec_command from ansible.module_utils.six import iteritems, string_types from ansible.module_utils.urls import fetch_url @@ -399,28 +399,6 @@ def is_nxapi(module): return 'nxapi' in (transport, provider_transport) -def to_command(module, commands): - if is_nxapi(module): - default_output = 'json' - else: - default_output = 'text' - - transform = ComplexList(dict( - command=dict(key=True), - output=dict(default=default_output), - prompt=dict(), - answer=dict() - ), module) - - commands = transform(to_list(commands)) - - for item in commands: - if is_json(item['command']): - item['output'] = 'json' - - return commands - - def get_config(module, flags=None): flags = [] if flags is None else flags @@ -430,7 +408,20 @@ def get_config(module, flags=None): def run_commands(module, commands, check_rc=True): conn = get_connection(module) - return conn.run_commands(to_command(module, commands), check_rc) + + if is_nxapi(module): + default_output = 'json' + else: + default_output = 'text' + + for index, cmd in enumerate(to_list(commands)): + if isinstance(cmd, string_types): + commands[index] = cmd = {'command': cmd, 'output': default_output} + + if is_json(cmd['command']): + cmd['output'] = 'json' + + return conn.run_commands(to_list(commands), check_rc) def load_config(module, config, return_error=False, opts=None): diff --git a/lib/ansible/modules/network/eos/eos_command.py b/lib/ansible/modules/network/eos/eos_command.py index 7d4c4cd18b2..8de1451c8c2 100644 --- a/lib/ansible/modules/network/eos/eos_command.py +++ b/lib/ansible/modules/network/eos/eos_command.py @@ -140,9 +140,8 @@ from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception from ansible.module_utils.six import string_types from ansible.module_utils.network.common.parsing import Conditional -from ansible.module_utils.network.common.utils import ComplexList from ansible.module_utils.network.eos.eos import run_commands -from ansible.module_utils.network.eos.eos import eos_argument_spec, check_args +from ansible.module_utils.network.eos.eos import eos_argument_spec VALID_KEYS = ['command', 'output', 'prompt', 'response'] @@ -157,16 +156,7 @@ def to_lines(stdout): def parse_commands(module, warnings): - spec = dict( - command=dict(key=True), - output=dict(), - prompt=dict(), - answer=dict() - ) - - transform = ComplexList(spec, module) - commands = transform(module.params['commands']) - + commands = module.params['commands'] if module.check_mode: for item in list(commands): if not item['command'].startswith('show'): @@ -189,8 +179,15 @@ def to_cli(obj): def main(): """entry point for module execution """ + command_spec = dict( + command=dict(key=True), + output=dict(), + prompt=dict(), + answer=dict() + ) + argument_spec = dict( - commands=dict(type='list', required=True), + commands=dict(type='list', elements='dict', options=command_spec, required=True), wait_for=dict(type='list', aliases=['waitfor']), match=dict(default='all', choices=['all', 'any']), @@ -207,7 +204,6 @@ def main(): result = {'changed': False} warnings = list() - check_args(module, warnings) commands = parse_commands(module, warnings) if warnings: result['warnings'] = warnings diff --git a/lib/ansible/modules/network/eos/eos_system.py b/lib/ansible/modules/network/eos/eos_system.py index 3ab319f5e70..3b525d57402 100644 --- a/lib/ansible/modules/network/eos/eos_system.py +++ b/lib/ansible/modules/network/eos/eos_system.py @@ -129,7 +129,6 @@ session_name: import re from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import ComplexList from ansible.module_utils.network.eos.eos import load_config, get_config from ansible.module_utils.network.eos.eos import eos_argument_spec @@ -270,31 +269,27 @@ def map_params_to_obj(module): obj = { 'hostname': module.params['hostname'], 'domain_name': module.params['domain_name'], - 'domain_list': module.params['domain_list'] + 'domain_list': module.params['domain_list'], + 'lookup_source': module.params['lookup_source'], + 'name_servers': module.params['name_servers'], } - lookup_source = ComplexList(dict( - interface=dict(key=True), - vrf=dict() - ), module) - - name_servers = ComplexList(dict( - server=dict(key=True), - vrf=dict(default='default') - ), module) - - for arg, cast in [('lookup_source', lookup_source), ('name_servers', name_servers)]: - if module.params[arg] is not None: - obj[arg] = cast(module.params[arg]) - else: - obj[arg] = None - return obj def main(): """ main entry point for module execution """ + lookup_source_spec = dict( + interface=dict(key=True), + vrf=dict() + ) + + name_servers_spec = dict( + server=dict(key=True), + vrf=dict() + ) + argument_spec = dict( hostname=dict(), @@ -302,10 +297,10 @@ def main(): domain_list=dict(type='list', aliases=['domain_search']), # { interface: , vrf: } - lookup_source=dict(type='list'), + lookup_source=dict(type='list', elements='dict', options=lookup_source_spec), # { server: ; vrf: } - name_servers=dict(type='list'), + name_servers=dict(type='list', elements='dict', options=name_servers_spec), state=dict(default='present', choices=['present', 'absent']) ) @@ -333,5 +328,6 @@ def main(): module.exit_json(**result) + if __name__ == '__main__': main() diff --git a/lib/ansible/modules/network/ios/ios_command.py b/lib/ansible/modules/network/ios/ios_command.py index a5c79d21941..7e6d0b31eae 100644 --- a/lib/ansible/modules/network/ios/ios_command.py +++ b/lib/ansible/modules/network/ios/ios_command.py @@ -134,9 +134,8 @@ failed_conditions: import time from ansible.module_utils.network.ios.ios import run_commands -from ansible.module_utils.network.ios.ios import ios_argument_spec, check_args +from ansible.module_utils.network.ios.ios import ios_argument_spec from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import ComplexList from ansible.module_utils.network.common.parsing import Conditional from ansible.module_utils.six import string_types @@ -149,13 +148,8 @@ def to_lines(stdout): def parse_commands(module, warnings): - command = ComplexList(dict( - command=dict(key=True), - prompt=dict(), - answer=dict() - ), module) - commands = command(module.params['commands']) - for item in list(commands): + commands = module.params['commands'] + for item in commands: if module.check_mode and not item['command'].startswith('show'): warnings.append( 'only show commands are supported when using check mode, not ' @@ -173,8 +167,14 @@ def parse_commands(module, warnings): def main(): """main entry point for module execution """ + command_spec = dict( + command=dict(key=True), + prompt=dict(), + answer=dict() + ) + argument_spec = dict( - commands=dict(type='list', required=True), + commands=dict(type='list', elements='dict', options=command_spec, required=True), wait_for=dict(type='list', aliases=['waitfor']), match=dict(default='all', choices=['all', 'any']), @@ -191,7 +191,6 @@ def main(): result = {'changed': False} warnings = list() - check_args(module, warnings) commands = parse_commands(module, warnings) result['warnings'] = warnings diff --git a/lib/ansible/modules/network/ios/ios_system.py b/lib/ansible/modules/network/ios/ios_system.py index 7b59e14859e..90f4d2750fa 100644 --- a/lib/ansible/modules/network/ios/ios_system.py +++ b/lib/ansible/modules/network/ios/ios_system.py @@ -120,8 +120,7 @@ import re from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import ios_argument_spec, check_args -from ansible.module_utils.network.common.utils import ComplexList +from ansible.module_utils.network.ios.ios import ios_argument_spec _CONFIGURED_VRFS = None @@ -307,44 +306,43 @@ def map_params_to_obj(module): 'hostname': module.params['hostname'], 'lookup_source': module.params['lookup_source'], 'lookup_enabled': module.params['lookup_enabled'], + 'domain_name': module.params['domain_name'], + 'domain_search': module.params['domain_search'], + 'name_servers': module.params['name_servers'] } - domain_name = ComplexList(dict( + return obj + + +def main(): + """ Main entry point for Ansible module execution + """ + domain_name_spec = dict( name=dict(key=True), vrf=dict() - ), module) + ) - domain_search = ComplexList(dict( + domain_search_spec = dict( name=dict(key=True), vrf=dict() - ), module) + ) - name_servers = ComplexList(dict( + name_servers_spec = dict( server=dict(key=True), vrf=dict() - ), module) - - for arg, cast in [('domain_name', domain_name), - ('domain_search', domain_search), - ('name_servers', name_servers)]: - - if module.params[arg]: - obj[arg] = cast(module.params[arg]) - else: - obj[arg] = None - - return obj - + ) -def main(): - """ Main entry point for Ansible module execution - """ argument_spec = dict( hostname=dict(), - domain_name=dict(type='list'), - domain_search=dict(type='list'), - name_servers=dict(type='list'), + # { name: , vrf: } + domain_name=dict(type='list', elements='dict', options=domain_name_spec), + + # {name: , vrf: } + domain_search=dict(type='list', elements='dict', options=domain_search_spec), + + # { server: ; vrf: } + name_servers=dict(type='list', elements='dict', options=name_servers_spec), lookup_source=dict(), lookup_enabled=dict(type='bool'), @@ -360,7 +358,6 @@ def main(): result = {'changed': False} warnings = list() - check_args(module, warnings) result['warnings'] = warnings want = map_params_to_obj(module) @@ -376,5 +373,6 @@ def main(): module.exit_json(**result) + if __name__ == "__main__": main() diff --git a/lib/ansible/modules/network/iosxr/iosxr_command.py b/lib/ansible/modules/network/iosxr/iosxr_command.py index 5fca0fdb262..bd05475d02e 100644 --- a/lib/ansible/modules/network/iosxr/iosxr_command.py +++ b/lib/ansible/modules/network/iosxr/iosxr_command.py @@ -127,8 +127,8 @@ import time from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.iosxr.iosxr import run_command, iosxr_argument_spec -from ansible.module_utils.network.iosxr.iosxr import command_spec from ansible.module_utils.network.common.parsing import Conditional +from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.six import string_types from ansible.module_utils._text import to_native @@ -142,11 +142,8 @@ def to_lines(stdout): def parse_commands(module, warnings): commands = module.params['commands'] - for item in list(commands): - try: - command = item['command'] - except Exception: - command = item + for item in to_list(commands): + command = item['command'] if module.check_mode and not command.startswith('show'): warnings.append( 'only show commands are supported when using check mode, not ' @@ -163,8 +160,14 @@ def parse_commands(module, warnings): def main(): + command_spec = dict( + command=dict(key=True), + prompt=dict(), + answer=dict() + ) + spec = dict( - commands=dict(type='list', required=True), + commands=dict(type='list', elements='dict', options=command_spec, required=True), wait_for=dict(type='list', aliases=['waitfor']), match=dict(default='all', choices=['all', 'any']), @@ -175,13 +178,10 @@ def main(): spec.update(iosxr_argument_spec) - spec.update(command_spec) - module = AnsibleModule(argument_spec=spec, supports_check_mode=True) warnings = list() - commands = parse_commands(module, warnings) wait_for = module.params['wait_for'] or list() diff --git a/lib/ansible/modules/network/nxos/nxos_command.py b/lib/ansible/modules/network/nxos/nxos_command.py index 8ebc0e9578f..5da430ac3c5 100644 --- a/lib/ansible/modules/network/nxos/nxos_command.py +++ b/lib/ansible/modules/network/nxos/nxos_command.py @@ -147,8 +147,7 @@ import time from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.network.common.parsing import Conditional, FailedConditionalError -from ansible.module_utils.network.common.utils import ComplexList -from ansible.module_utils.network.nxos.nxos import check_args, nxos_argument_spec, run_commands +from ansible.module_utils.network.nxos.nxos import nxos_argument_spec, run_commands from ansible.module_utils.six import string_types from ansible.module_utils._text import to_native @@ -163,14 +162,7 @@ def to_lines(stdout): def parse_commands(module, warnings): - transform = ComplexList(dict( - command=dict(key=True), - output=dict(), - prompt=dict(), - answer=dict() - ), module) - - commands = transform(module.params['commands']) + commands = module.params['commands'] if module.check_mode: for item in list(commands): @@ -194,9 +186,16 @@ def to_cli(obj): def main(): """entry point for module execution """ + command_spec = dict( + command=dict(key=True), + output=dict(), + prompt=dict(), + answer=dict() + ) + argument_spec = dict( # { command: , output: , prompt: , response: } - commands=dict(type='list', required=True), + commands=dict(type='list', elements='dict', options=command_spec, required=True), wait_for=dict(type='list', aliases=['waitfor']), match=dict(default='all', choices=['any', 'all']), @@ -213,7 +212,6 @@ def main(): result = {'changed': False} warnings = list() - check_args(module, warnings) commands = parse_commands(module, warnings) result['warnings'] = warnings diff --git a/lib/ansible/modules/network/nxos/nxos_system.py b/lib/ansible/modules/network/nxos/nxos_system.py index ac236ee355e..e616db75863 100644 --- a/lib/ansible/modules/network/nxos/nxos_system.py +++ b/lib/ansible/modules/network/nxos/nxos_system.py @@ -112,11 +112,10 @@ commands: import re from ansible.module_utils.network.nxos.nxos import get_config, load_config -from ansible.module_utils.network.nxos.nxos import nxos_argument_spec, check_args +from ansible.module_utils.network.nxos.nxos import nxos_argument_spec from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.six import iteritems from ansible.module_utils.network.common.config import NetworkConfig -from ansible.module_utils.network.common.utils import ComplexList _CONFIGURED_VRFS = None @@ -302,49 +301,45 @@ def map_params_to_obj(module): obj = { 'hostname': module.params['hostname'], 'domain_lookup': module.params['domain_lookup'], - 'system_mtu': module.params['system_mtu'] + 'system_mtu': module.params['system_mtu'], + 'domain_name': module.params['domain_name'], + 'domain_search': module.params['domain_search'], + 'name_servers': module.params['name_servers'] } - domain_name = ComplexList(dict( + return obj + + +def main(): + """ main entry point for module execution + """ + domain_name_spec = dict( name=dict(key=True), vrf=dict() - ), module) + ) - domain_search = ComplexList(dict( + domain_search_spec = dict( name=dict(key=True), vrf=dict() - ), module) + ) - name_servers = ComplexList(dict( + name_servers_spec = dict( server=dict(key=True), vrf=dict() - ), module) - - for arg, cast in [('domain_name', domain_name), ('domain_search', domain_search), - ('name_servers', name_servers)]: - if module.params[arg] is not None: - obj[arg] = cast(module.params[arg]) - else: - obj[arg] = None - - return obj - + ) -def main(): - """ main entry point for module execution - """ argument_spec = dict( hostname=dict(), domain_lookup=dict(type='bool'), # { name: , vrf: } - domain_name=dict(type='list'), + domain_name=dict(type='list', elements='dict', options=domain_name_spec), # {name: , vrf: } - domain_search=dict(type='list'), + domain_search=dict(type='list', elements='dict', options=domain_search_spec), # { server: ; vrf: } - name_servers=dict(type='list'), + name_servers=dict(type='list', elements='dict', options=name_servers_spec), system_mtu=dict(type='int'), lookup_source=dict(), @@ -357,7 +352,6 @@ def main(): supports_check_mode=True) warnings = list() - check_args(module, warnings) result = {'changed': False} if warnings: @@ -376,5 +370,6 @@ def main(): module.exit_json(**result) + if __name__ == '__main__': main() diff --git a/lib/ansible/modules/network/vyos/vyos_command.py b/lib/ansible/modules/network/vyos/vyos_command.py index 798ec0077a9..da3edf45c62 100644 --- a/lib/ansible/modules/network/vyos/vyos_command.py +++ b/lib/ansible/modules/network/vyos/vyos_command.py @@ -137,7 +137,6 @@ import time from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception from ansible.module_utils.network.common.parsing import Conditional -from ansible.module_utils.network.common.utils import ComplexList from ansible.module_utils.six import string_types from ansible.module_utils.network.vyos.vyos import run_commands from ansible.module_utils.network.vyos.vyos import vyos_argument_spec @@ -151,12 +150,7 @@ def to_lines(stdout): def parse_commands(module, warnings): - command = ComplexList(dict( - command=dict(key=True), - prompt=dict(), - answer=dict(), - ), module) - commands = command(module.params['commands']) + commands = module.params['commands'] items = [] for item in commands: @@ -170,8 +164,15 @@ def parse_commands(module, warnings): def main(): + + command_spec = dict( + command=dict(key=True), + prompt=dict(), + answer=dict() + ) + spec = dict( - commands=dict(type='list', required=True), + commands=dict(type='list', elements='dict', options=command_spec, required=True), wait_for=dict(type='list', aliases=['waitfor']), match=dict(default='all', choices=['all', 'any']), diff --git a/test/units/module_utils/test_basic.py b/test/units/module_utils/test_basic.py index 4df155bc084..a575bcda4d9 100644 --- a/test/units/module_utils/test_basic.py +++ b/test/units/module_utils/test_basic.py @@ -575,6 +575,21 @@ class TestModuleUtilsBasic(ModuleTestCase): supports_check_mode=True, ) + # should test ok, handles key argument + key_spec = dict(foo=dict(key=True), bar=dict()) + args = json.dumps(dict(ANSIBLE_MODULE_ARGS={'foobar': ['test-1', 'test-2']})) + with swap_stdin_and_argv(stdin_data=args): + basic._ANSIBLE_ARGS = None + am = basic.AnsibleModule( + argument_spec=dict(foobar=dict(type='list', elements='dict', options=key_spec, required=True)), + no_log=True, + check_invalid_arguments=False, + add_file_common_args=True, + supports_check_mode=True + ) + self.assertEqual(am.params['foobar'][0]['foo'], 'test-1') + self.assertEqual(am.params['foobar'][1]['foo'], 'test-2') + def test_module_utils_basic_ansible_module_type_check(self): from ansible.module_utils import basic