Revert "Deprecate Entity, EntityCollection and use subspec in network modules (#33575)" (#33849)

This reverts commit 4349b56643.
pull/33987/head
Ganesh Nalawade 7 years ago committed by GitHub
parent b6528ea19f
commit ea18b9021a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1929,23 +1929,14 @@ 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 index, param in enumerate(elements):
for param in elements:
if not isinstance(param, dict):
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.fail_json(msg="value of %s must be of type dict or list of dict" % k)
self._set_fallbacks(spec, param)
options_aliases = self._handle_aliases(spec, param)

@ -65,10 +65,6 @@ 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.
@ -187,12 +183,7 @@ class Entity(object):
class EntityCollection(Entity):
"""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.
"""
"""Extends ```Entity``` to handle a list of dicts """
def __call__(self, iterable, strict=True):
if iterable is None:
@ -207,21 +198,11 @@ 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)

@ -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
from ansible.module_utils.six import iteritems, string_types
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.six import iteritems
from ansible.module_utils.urls import fetch_url
_DEVICE_CONNECTION = None
@ -150,6 +150,7 @@ 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')
@ -428,6 +429,22 @@ 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
@ -437,15 +454,7 @@ def get_config(module, flags=None):
def run_commands(module, commands):
conn = get_connection(module)
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))
return conn.run_commands(to_command(module, commands))
def load_config(module, config, commit=False, replace=False):

@ -27,9 +27,8 @@
#
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 = {}
@ -101,12 +100,20 @@ 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()
for cmd in to_list(commands):
if isinstance(cmd, string_types):
cmd = {'command': cmd}
commands = to_commands(module, to_list(commands))
for cmd in commands:
cmd = module.jsonify(cmd)
rc, out, err = exec_command(module, cmd)
if check_rc and rc != 0:

@ -79,6 +79,12 @@ 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'),

@ -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
from ansible.module_utils.network.common.utils import to_list, ComplexList
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,6 +399,28 @@ 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
@ -408,20 +430,7 @@ def get_config(module, flags=None):
def run_commands(module, commands, check_rc=True):
conn = get_connection(module)
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)
return conn.run_commands(to_command(module, commands), check_rc)
def load_config(module, config, return_error=False, opts=None):

@ -140,8 +140,9 @@ 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
from ansible.module_utils.network.eos.eos import eos_argument_spec, check_args
VALID_KEYS = ['command', 'output', 'prompt', 'response']
@ -156,7 +157,16 @@ def to_lines(stdout):
def parse_commands(module, warnings):
commands = module.params['commands']
spec = dict(
command=dict(key=True),
output=dict(),
prompt=dict(),
answer=dict()
)
transform = ComplexList(spec, module)
commands = transform(module.params['commands'])
if module.check_mode:
for item in list(commands):
if not item['command'].startswith('show'):
@ -179,15 +189,8 @@ 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', elements='dict', options=command_spec, required=True),
commands=dict(type='list', required=True),
wait_for=dict(type='list', aliases=['waitfor']),
match=dict(default='all', choices=['all', 'any']),
@ -204,6 +207,7 @@ def main():
result = {'changed': False}
warnings = list()
check_args(module, warnings)
commands = parse_commands(module, warnings)
if warnings:
result['warnings'] = warnings

@ -129,6 +129,7 @@ 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
@ -269,27 +270,31 @@ def map_params_to_obj(module):
obj = {
'hostname': module.params['hostname'],
'domain_name': module.params['domain_name'],
'domain_list': module.params['domain_list'],
'lookup_source': module.params['lookup_source'],
'name_servers': module.params['name_servers'],
'domain_list': module.params['domain_list']
}
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(),
@ -297,10 +302,10 @@ def main():
domain_list=dict(type='list', aliases=['domain_search']),
# { interface: <str>, vrf: <str> }
lookup_source=dict(type='list', elements='dict', options=lookup_source_spec),
lookup_source=dict(type='list'),
# { server: <str>; vrf: <str> }
name_servers=dict(type='list', elements='dict', options=name_servers_spec),
name_servers=dict(type='list'),
state=dict(default='present', choices=['present', 'absent'])
)
@ -328,6 +333,5 @@ def main():
module.exit_json(**result)
if __name__ == '__main__':
main()

@ -134,8 +134,9 @@ 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
from ansible.module_utils.network.ios.ios import ios_argument_spec, check_args
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
@ -148,8 +149,13 @@ def to_lines(stdout):
def parse_commands(module, warnings):
commands = module.params['commands']
for item in commands:
command = ComplexList(dict(
command=dict(key=True),
prompt=dict(),
answer=dict()
), module)
commands = command(module.params['commands'])
for item in list(commands):
if module.check_mode and not item['command'].startswith('show'):
warnings.append(
'only show commands are supported when using check mode, not '
@ -167,14 +173,8 @@ 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', elements='dict', options=command_spec, required=True),
commands=dict(type='list', required=True),
wait_for=dict(type='list', aliases=['waitfor']),
match=dict(default='all', choices=['all', 'any']),
@ -191,6 +191,7 @@ def main():
result = {'changed': False}
warnings = list()
check_args(module, warnings)
commands = parse_commands(module, warnings)
result['warnings'] = warnings

@ -120,7 +120,8 @@ 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
from ansible.module_utils.network.ios.ios import ios_argument_spec, check_args
from ansible.module_utils.network.common.utils import ComplexList
_CONFIGURED_VRFS = None
@ -306,43 +307,44 @@ 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']
}
return obj
def main():
""" Main entry point for Ansible module execution
"""
domain_name_spec = dict(
domain_name = ComplexList(dict(
name=dict(key=True),
vrf=dict()
)
), module)
domain_search_spec = dict(
domain_search = ComplexList(dict(
name=dict(key=True),
vrf=dict()
)
), module)
name_servers_spec = dict(
name_servers = ComplexList(dict(
server=dict(key=True),
vrf=dict()
)
), module)
argument_spec = dict(
hostname=dict(),
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
# { name: <str>, vrf: <str> }
domain_name=dict(type='list', elements='dict', options=domain_name_spec),
return obj
# {name: <str>, vrf: <str> }
domain_search=dict(type='list', elements='dict', options=domain_search_spec),
# { server: <str>; vrf: <str> }
name_servers=dict(type='list', elements='dict', options=name_servers_spec),
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'),
lookup_source=dict(),
lookup_enabled=dict(type='bool'),
@ -358,6 +360,7 @@ def main():
result = {'changed': False}
warnings = list()
check_args(module, warnings)
result['warnings'] = warnings
want = map_params_to_obj(module)
@ -373,6 +376,5 @@ def main():
module.exit_json(**result)
if __name__ == "__main__":
main()

@ -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,8 +142,11 @@ def to_lines(stdout):
def parse_commands(module, warnings):
commands = module.params['commands']
for item in to_list(commands):
command = item['command']
for item in list(commands):
try:
command = item['command']
except Exception:
command = item
if module.check_mode and not command.startswith('show'):
warnings.append(
'only show commands are supported when using check mode, not '
@ -160,14 +163,8 @@ def parse_commands(module, warnings):
def main():
command_spec = dict(
command=dict(key=True),
prompt=dict(),
answer=dict()
)
spec = dict(
commands=dict(type='list', elements='dict', options=command_spec, required=True),
commands=dict(type='list', required=True),
wait_for=dict(type='list', aliases=['waitfor']),
match=dict(default='all', choices=['all', 'any']),
@ -178,10 +175,13 @@ 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()

@ -147,7 +147,8 @@ import time
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.common.parsing import Conditional, FailedConditionalError
from ansible.module_utils.network.nxos.nxos import nxos_argument_spec, run_commands
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.six import string_types
from ansible.module_utils._text import to_native
@ -162,7 +163,14 @@ def to_lines(stdout):
def parse_commands(module, warnings):
commands = module.params['commands']
transform = ComplexList(dict(
command=dict(key=True),
output=dict(),
prompt=dict(),
answer=dict()
), module)
commands = transform(module.params['commands'])
if module.check_mode:
for item in list(commands):
@ -186,16 +194,9 @@ 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: <str>, output: <str>, prompt: <str>, response: <str> }
commands=dict(type='list', elements='dict', options=command_spec, required=True),
commands=dict(type='list', required=True),
wait_for=dict(type='list', aliases=['waitfor']),
match=dict(default='all', choices=['any', 'all']),
@ -212,6 +213,7 @@ def main():
result = {'changed': False}
warnings = list()
check_args(module, warnings)
commands = parse_commands(module, warnings)
result['warnings'] = warnings

@ -112,10 +112,11 @@ 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
from ansible.module_utils.network.nxos.nxos import nxos_argument_spec, check_args
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
@ -301,45 +302,49 @@ def map_params_to_obj(module):
obj = {
'hostname': module.params['hostname'],
'domain_lookup': module.params['domain_lookup'],
'system_mtu': module.params['system_mtu'],
'domain_name': module.params['domain_name'],
'domain_search': module.params['domain_search'],
'name_servers': module.params['name_servers']
'system_mtu': module.params['system_mtu']
}
return obj
def main():
""" main entry point for module execution
"""
domain_name_spec = dict(
domain_name = ComplexList(dict(
name=dict(key=True),
vrf=dict()
)
), module)
domain_search_spec = dict(
domain_search = ComplexList(dict(
name=dict(key=True),
vrf=dict()
)
), module)
name_servers_spec = dict(
name_servers = ComplexList(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: <str>, vrf: <str> }
domain_name=dict(type='list', elements='dict', options=domain_name_spec),
domain_name=dict(type='list'),
# {name: <str>, vrf: <str> }
domain_search=dict(type='list', elements='dict', options=domain_search_spec),
domain_search=dict(type='list'),
# { server: <str>; vrf: <str> }
name_servers=dict(type='list', elements='dict', options=name_servers_spec),
name_servers=dict(type='list'),
system_mtu=dict(type='int'),
lookup_source=dict(),
@ -352,6 +357,7 @@ def main():
supports_check_mode=True)
warnings = list()
check_args(module, warnings)
result = {'changed': False}
if warnings:
@ -370,6 +376,5 @@ def main():
module.exit_json(**result)
if __name__ == '__main__':
main()

@ -137,6 +137,7 @@ 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
@ -150,7 +151,12 @@ def to_lines(stdout):
def parse_commands(module, warnings):
commands = module.params['commands']
command = ComplexList(dict(
command=dict(key=True),
prompt=dict(),
answer=dict(),
), module)
commands = command(module.params['commands'])
items = []
for item in commands:
@ -164,15 +170,8 @@ def parse_commands(module, warnings):
def main():
command_spec = dict(
command=dict(key=True),
prompt=dict(),
answer=dict()
)
spec = dict(
commands=dict(type='list', elements='dict', options=command_spec, required=True),
commands=dict(type='list', required=True),
wait_for=dict(type='list', aliases=['waitfor']),
match=dict(default='all', choices=['all', 'any']),

@ -575,21 +575,6 @@ 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

Loading…
Cancel
Save