First implementation of 'fallback' parameter

Implemented & documented for EOS & NXOS
pull/15226/head
Nathaniel Case 9 years ago
parent 2e55b3567b
commit dbc49ad95b

@ -516,6 +516,18 @@ def is_executable(path):
or stat.S_IXOTH & os.stat(path)[stat.ST_MODE]) or stat.S_IXOTH & os.stat(path)[stat.ST_MODE])
class AnsibleFallbackNotFound(Exception):
pass
def env_fallback(*args, **kwargs):
''' Load value from environment '''
for arg in args:
if arg in os.environ:
return os.environ[arg]
else:
raise AnsibleFallbackNotFound
class AnsibleModule(object): class AnsibleModule(object):
def __init__(self, argument_spec, bypass_checks=False, no_log=False, def __init__(self, argument_spec, bypass_checks=False, no_log=False,
check_invalid_arguments=True, mutually_exclusive=None, required_together=None, check_invalid_arguments=True, mutually_exclusive=None, required_together=None,
@ -550,6 +562,7 @@ class AnsibleModule(object):
self._load_constants() self._load_constants()
self._load_params() self._load_params()
self._set_fallbacks()
# append to legal_inputs and then possibly check against them # append to legal_inputs and then possibly check against them
try: try:
@ -1421,6 +1434,23 @@ class AnsibleModule(object):
if k not in self.params: if k not in self.params:
self.params[k] = default self.params[k] = default
def _set_fallbacks(self):
for k,v in self.argument_spec.items():
fallback = v.get('fallback', (None,))
fallback_strategy = fallback[0]
fallback_args = []
fallback_kwargs = {}
if k not in self.params and fallback_strategy is not None:
for item in fallback[1:]:
if isinstance(item, dict):
fallback_kwargs = item
else:
fallback_args = item
try:
self.params[k] = fallback_strategy(*fallback_args, **fallback_kwargs)
except AnsibleFallbackNotFound:
continue
def _load_params(self): def _load_params(self):
''' read the input and set the params attribute''' ''' read the input and set the params attribute'''
if MODULE_COMPLEX_ARGS is None: if MODULE_COMPLEX_ARGS is None:

@ -20,7 +20,7 @@ import os
import re import re
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule, env_fallback
from ansible.module_utils.shell import Shell, Command, HAS_PARAMIKO from ansible.module_utils.shell import Shell, Command, HAS_PARAMIKO
from ansible.module_utils.netcfg import parse from ansible.module_utils.netcfg import parse
from ansible.module_utils.urls import fetch_url from ansible.module_utils.urls import fetch_url
@ -30,24 +30,16 @@ NET_PASSWD_RE = re.compile(r"[\r\n]?password: $", re.I)
NET_COMMON_ARGS = dict( NET_COMMON_ARGS = dict(
host=dict(required=True), host=dict(required=True),
port=dict(type='int'), port=dict(type='int'),
username=dict(required=True), username=dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
password=dict(no_log=True), password=dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD'])),
ssh_keyfile=dict(type='path'), ssh_keyfile=dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
authorize=dict(default=False, type='bool'), authorize=dict(default=False, fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'),
auth_pass=dict(no_log=True), auth_pass=dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS'])),
transport=dict(default='cli', choices=['cli', 'eapi']), transport=dict(default='cli', choices=['cli', 'eapi']),
use_ssl=dict(default=True, type='bool'), use_ssl=dict(default=True, type='bool'),
provider=dict(type='dict') provider=dict(type='dict')
) )
NET_ENV_ARGS = dict(
username='ANSIBLE_NET_USERNAME',
password='ANSIBLE_NET_PASSWORD',
ssh_keyfile='ANSIBLE_NET_SSH_KEYFILE',
authorize='ANSIBLE_NET_AUTHORIZE',
auth_pass='ANSIBLE_NET_AUTH_PASS',
)
CLI_PROMPTS_RE = [ CLI_PROMPTS_RE = [
re.compile(r"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"), re.compile(r"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
re.compile(r"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$") re.compile(r"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$")
@ -200,9 +192,6 @@ class NetworkModule(AnsibleModule):
if key in NET_COMMON_ARGS: if key in NET_COMMON_ARGS:
if self.params.get(key) is None and value is not None: if self.params.get(key) is None and value is not None:
self.params[key] = value self.params[key] = value
for key, env_var in NET_ENV_ARGS.items():
if self.params.get(key) is None and env_var in os.environ:
self.params[key] = os.environ[env_var]
def connect(self): def connect(self):
try: try:

@ -21,7 +21,7 @@ import re
from ansible.module_utils.urls import fetch_url from ansible.module_utils.urls import fetch_url
from ansible.module_utils.shell import Shell, HAS_PARAMIKO from ansible.module_utils.shell import Shell, HAS_PARAMIKO
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule, env_fallback
from ansible.module_utils.netcfg import parse from ansible.module_utils.netcfg import parse
NET_PASSWD_RE = re.compile(r"[\r\n]?password: $", re.I) NET_PASSWD_RE = re.compile(r"[\r\n]?password: $", re.I)
@ -29,8 +29,9 @@ NET_PASSWD_RE = re.compile(r"[\r\n]?password: $", re.I)
NET_COMMON_ARGS = dict( NET_COMMON_ARGS = dict(
host=dict(required=True), host=dict(required=True),
port=dict(type='int'), port=dict(type='int'),
username=dict(required=True), username=dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
password=dict(no_log=True), password=dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD'])),
ssh_keyfile=dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
transport=dict(default='cli', choices=['cli', 'nxapi']), transport=dict(default='cli', choices=['cli', 'nxapi']),
use_ssl=dict(default=False, type='bool'), use_ssl=dict(default=False, type='bool'),
validate_certs=dict(default=True, type='bool'), validate_certs=dict(default=True, type='bool'),
@ -165,11 +166,11 @@ class Cli(object):
username = self.module.params['username'] username = self.module.params['username']
password = self.module.params['password'] password = self.module.params['password']
key_filename = self.module.params['ssh_keyfile']
try: try:
self.shell = Shell(prompts_re=CLI_PROMPTS_RE, errors_re=CLI_ERRORS_RE, self.shell = Shell(prompts_re=CLI_PROMPTS_RE, errors_re=CLI_ERRORS_RE, kickstart=False)
kickstart=False) self.shell.open(host, port=port, username=username, password=password, key_filename=key_filename)
self.shell.open(host, port=port, username=username, password=password)
except Exception, exc: except Exception, exc:
msg = 'failed to connect to %s:%s - %s' % (host, port, str(exc)) msg = 'failed to connect to %s:%s - %s' % (host, port, str(exc))
self.module.fail_json(msg=msg) self.module.fail_json(msg=msg)

@ -41,26 +41,31 @@ options:
- Configures the usename to use to authenticate the connection to - Configures the usename to use to authenticate the connection to
the remote device. The value of I(username) is used to authenticate the remote device. The value of I(username) is used to authenticate
either the CLI login or the eAPI authentication depending on which either the CLI login or the eAPI authentication depending on which
transport is used. transport is used. If the value is not specified in the task, the
required: true value of environment variable ANSIBLE_NET_USERNAME will be used instead.
required: false
password: password:
description: description:
- Specifies the password to use to authenticate the connection to - Specifies the password to use to authenticate the connection to
the remote device. This is a common argument used for either I(cli) the remote device. This is a common argument used for either I(cli)
or I(eapi) transports. or I(eapi) transports. If the value is not specified in the task, the
value of environment variable ANSIBLE_NET_PASSWORD will be used instead.
required: false required: false
default: null default: null
ssh_keyfile: ssh_keyfile:
description: description:
- Specifies the SSH keyfile to use to authenticate the connection to - Specifies the SSH keyfile to use to authenticate the connection to
the remote device. This argument is only used for I(cli) transports. the remote device. This argument is only used for I(cli) transports.
If the value is not specified in the task, the value of environment
variable ANSIBLE_NET_SSH_KEYFILE will be used instead.
required: false required: false
default: null
authorize: authorize:
description: description:
- Instructs the module to enter priviledged mode on the remote device - Instructs the module to enter priviledged mode on the remote device
before sending any commands. If not specified, the device will before sending any commands. If not specified, the device will
attempt to excecute all commands in non-priviledged mode. attempt to excecute all commands in non-priviledged mode. If the value
is not specified in the task, the value of environment variable
ANSIBLE_NET_AUTHORIZE will be used instead.
required: false required: false
default: no default: no
choices: ['yes', 'no'] choices: ['yes', 'no']
@ -68,7 +73,8 @@ options:
description: description:
- Specifies the password to use if required to enter privileged mode - Specifies the password to use if required to enter privileged mode
on the remote device. If I(authorize) is false, then this argument on the remote device. If I(authorize) is false, then this argument
does nothing does nothing. If the value is not specified in the task, the value of
environment variable ANSIBLE_NET_AUTH_PASS will be used instead.
required: false required: false
default: none default: none
transport: transport:

@ -41,15 +41,24 @@ options:
- Configures the usename to use to authenticate the connection to - Configures the usename to use to authenticate the connection to
the remote device. The value of I(username) is used to authenticate the remote device. The value of I(username) is used to authenticate
either the CLI login or the nxapi authentication depending on which either the CLI login or the nxapi authentication depending on which
transport is used. transport is used. If the value is not specified in the task, the
required: true value of environment variable ANSIBLE_NET_USERNAME will be used instead.
required: false
password: password:
description: description:
- Specifies the password to use when authentication the connection to - Specifies the password to use to authenticate the connection to
the remote device. This is a common argument used for either I(cli) the remote device. This is a common argument used for either I(cli)
or I(nxapi) transports. or I(nxapi) transports. If the value is not specified in the task, the
value of environment variable ANSIBLE_NET_PASSWORD will be used instead.
required: false required: false
default: null default: null
ssh_keyfile:
description:
- Specifies the SSH key to use to authenticate the connection to
the remote device. This argument is only used for the I(cli)
transport. If the value is not specified in the task, the
value of environment variable ANSIBLE_NET_SSH_KEYFILE will be used instead.
required: false
transport: transport:
description: description:
- Configures the transport connection to use when connecting to the - Configures the transport connection to use when connecting to the

Loading…
Cancel
Save