summaryrefslogtreecommitdiff
path: root/network/asa
diff options
context:
space:
mode:
authorPeter Sprygada <privateip@users.noreply.github.com>2016-09-04 21:00:15 -0400
committerGitHub <noreply@github.com>2016-09-04 21:00:15 -0400
commitd3dd754a40fe7068c8f5fbd95876273781a72c56 (patch)
tree61393d15a942e92ab4199c83f0a0f0046970710e /network/asa
parent84953d9d422a467e2d406452956c7351359e5a5c (diff)
parentdb5dd8516c252be682f2e23cf61eb17ea0622a02 (diff)
downloadansible-modules-extras-d3dd754a40fe7068c8f5fbd95876273781a72c56.tar.gz
Merge pull request #2848 from privateip/asa_config
update asa_config module
Diffstat (limited to 'network/asa')
-rw-r--r--network/asa/asa_config.py260
1 files changed, 191 insertions, 69 deletions
diff --git a/network/asa/asa_config.py b/network/asa/asa_config.py
index 7c7d1248..36926227 100644
--- a/network/asa/asa_config.py
+++ b/network/asa/asa_config.py
@@ -20,7 +20,7 @@ DOCUMENTATION = """
---
module: asa_config
version_added: "2.2"
-author: "Peter Sprygada (@privateip) & Patrick Ogenstad (@ogenstad)"
+author: "Peter Sprygada (@privateip), Patrick Ogenstad (@ogenstad)"
short_description: Manage Cisco ASA configuration sections
description:
- Cisco ASA configurations use a simple block indent file sytanx
@@ -34,9 +34,11 @@ options:
- The ordered set of commands that should be configured in the
section. The commands must be the exact same commands as found
in the device running-config. Be sure to note the configuration
- command syntanx as some commands are automatically modified by the
+ command syntax as some commands are automatically modified by the
device config parser.
- required: true
+ required: false
+ default: null
+ aliases: ['commands']
parents:
description:
- The ordered set of parents that uniquely identify the section
@@ -45,6 +47,15 @@ options:
level or global commands.
required: false
default: null
+ src:
+ description:
+ - Specifies the source path to the file that contains the configuration
+ or configuration template to load. The path to the source file can
+ either be the full path on the Ansible control host or a relative
+ path from the playbook or role root directory. This argument is mutually
+ exclusive with I(lines).
+ required: false
+ default: null
before:
description:
- The ordered set of commands to push on to the command stack if
@@ -57,7 +68,7 @@ options:
after:
description:
- The ordered set of commands to append to the end of the command
- stack if a changed needs to be made. Just like with I(before) this
+ stack if a change needs to be made. Just like with I(before) this
allows the playbook designer to append a set of commands to be
executed after the command set.
required: false
@@ -68,11 +79,13 @@ options:
the set of commands against the current device config. If
match is set to I(line), commands are matched line by line. If
match is set to I(strict), command lines are matched with respect
- to position. Finally if match is set to I(exact), command lines
- must be an equal match.
+ to position. If match is set to I(exact), command lines
+ must be an equal match. Finally, if match is set to I(none), the
+ module will not attempt to compare the source configuration with
+ the running configuration on the remote device.
required: false
default: line
- choices: ['line', 'strict', 'exact']
+ choices: ['line', 'strict', 'exact', 'none']
replace:
description:
- Instructs the module on the way to perform the configuration
@@ -84,35 +97,84 @@ options:
required: false
default: line
choices: ['line', 'block']
- force:
+ update:
+ description:
+ - The I(update) argument controls how the configuration statements
+ are processed on the remote device. Valid choices for the I(update)
+ argument are I(merge) and I(check). When the argument is set to
+ I(merge), the configuration changes are merged with the current
+ device running configuration. When the argument is set to I(check)
+ the configuration updates are determined but not actually configured
+ on the remote device.
+ required: false
+ default: merge
+ choices: ['merge', 'check']
+ commit:
description:
- - The force argument instructs the module to not consider the
- current devices running-config. When set to true, this will
- cause the module to push the contents of I(src) into the device
- without first checking if already configured.
+ - This argument specifies the update method to use when applying the
+ configuration changes to the remote node. If the value is set to
+ I(merge) the configuration updates are merged with the running-
+ config. If the value is set to I(check), no changes are made to
+ the remote host.
required: false
- default: false
+ default: merge
+ choices: ['merge', 'check']
+ backup:
+ description:
+ - This argument will cause the module to create a full backup of
+ the current C(running-config) from the remote device before any
+ changes are made. The backup file is written to the C(backup)
+ folder in the playbook root directory. If the directory does not
+ exist, it is created.
+ required: false
+ default: no
choices: ['yes', 'no']
config:
description:
- - The module, by default, will connect to the remote device and
- retrieve the current running-config to use as a base for comparing
- against the contents of source. There are times when it is not
- desirable to have the task get the current running-config for
- every task in a playbook. The I(config) argument allows the
- implementer to pass in the configuruation to use as the base
- config for comparision.
+ - The C(config) argument allows the playbook desginer to supply
+ the base configuration to be used to validate configuration
+ changes necessary. If this argument is provided, the module
+ will not download the running-config from the remote node.
required: false
default: null
+ default:
+ description:
+ - This argument specifies whether or not to collect all defaults
+ when getting the remote device running config. When enabled,
+ the module will get the current config by issuing the command
+ C(show running-config all).
+ required: false
+ default: no
+ choices: ['yes', 'no']
+ save:
+ description:
+ - The C(save) argument instructs the module to save the running-
+ config to the startup-config at the conclusion of the module
+ running. If check mode is specified, this argument is ignored.
+ required: false
+ default: no
+ choices: ['yes', 'no']
"""
EXAMPLES = """
+# Note: examples below use the following provider dict to handle
+# transport and authentication to the node.
+vars:
+ cli:
+ host: "{{ inventory_hostname }}"
+ username: cisco
+ password: cisco
+ authorize: yes
+ auth_pass: cisco
+ transport: cli
+
- asa_config:
lines:
- network-object host 10.80.30.18
- network-object host 10.80.30.19
- network-object host 10.80.30.20
parents: ['object-group network OG-MONITORED-SERVERS']
+ provider: "{{ cli }}"
- asa_config:
host: "{{ inventory_hostname }}"
@@ -128,12 +190,11 @@ EXAMPLES = """
context: ansible
- asa_config:
- provider: "{{ cli }}"
- host: "{{ inventory_hostname }}"
show_command: 'more system:running-config'
lines:
- ikev1 pre-shared-key MyS3cretVPNK3y
parents: tunnel-group 1.1.1.1 ipsec-attributes
+ provider: "{{ cli }}"
"""
@@ -143,79 +204,140 @@ updates:
returned: always
type: list
sample: ['...', '...']
-
+backup_path:
+ description: The full path to the backup file
+ returned: when backup is yes
+ type: path
+ sample: /playbooks/ansible/backup/config.2016-07-16@22:28:34
responses:
description: The set of responses from issuing the commands on the device
- retured: when not check_mode
+ returned: when not check_mode
type: list
sample: ['...', '...']
"""
+import re
+
+from ansible.module_utils.basic import get_exception
+from ansible.module_utils.asa import NetworkModule, NetworkError
+from ansible.module_utils.netcfg import NetworkConfig, dumps
+from ansible.module_utils.netcli import Command
+
+def invoke(name, *args, **kwargs):
+ func = globals().get(name)
+ if func:
+ return func(*args, **kwargs)
-def get_config(module):
- config = module.params['config'] or dict()
- if not config and not module.params['force']:
- config = module.config
- return config
+def check_args(module, warnings):
+ if module.params['parents']:
+ if not module.params['lines'] or module.params['src']:
+ warnings.append('ignoring unnecessary argument parents')
+ if module.params['match'] == 'none' and module.params['replace']:
+ warnings.append('ignoring unnecessary argument replace')
+def get_config(module, result):
+ defaults = module.params['default']
+ if defaults is True:
+ key = '__configall__'
+ else:
+ key = '__config__'
+
+ contents = module.params['config'] or result.get(key)
+
+ if not contents:
+ contents = module.config.get_config(include_defaults=defaults)
+ result[key] = contents
+
+ return NetworkConfig(indent=1, contents=contents)
+
+def get_candidate(module):
+ candidate = NetworkConfig(indent=1)
+ if module.params['src']:
+ candidate.load(module.params['src'])
+ elif module.params['lines']:
+ parents = module.params['parents'] or list()
+ candidate.add(module.params['lines'], parents=parents)
+ return candidate
+
+def load_config(module, commands, result):
+ if not module.check_mode and module.params['update'] != 'check':
+ module.config(commands)
+ result['changed'] = module.params['update'] != 'check'
+ result['updates'] = commands.split('\n')
+
+def run(module, result):
+ match = module.params['match']
+ replace = module.params['replace']
+
+ candidate = get_candidate(module)
+
+ if match != 'none':
+ config = get_config(module, result)
+ configobjs = candidate.difference(config, match=match, replace=replace)
+ else:
+ config = None
+ configobjs = candidate.items
+
+ if configobjs:
+ commands = dumps(configobjs, 'commands')
+
+ if module.params['before']:
+ commands[:0] = module.params['before']
+
+ if module.params['after']:
+ commands.extend(module.params['after'])
+
+ # send the configuration commands to the device and merge
+ # them with the current running config
+ load_config(module, commands, result)
+
+ if module.params['save'] and not module.check_mode:
+ module.config.save_config()
def main():
argument_spec = dict(
- lines=dict(aliases=['commands'], required=True, type='list'),
+ lines=dict(aliases=['commands'], type='list'),
parents=dict(type='list'),
+
+ src=dict(type='path'),
+
before=dict(type='list'),
after=dict(type='list'),
- match=dict(default='line', choices=['line', 'strict', 'exact']),
- replace=dict(default='line', choices=['line', 'block']),
- force=dict(default=False, type='bool'),
- config=dict()
- )
- module = get_module(argument_spec=argument_spec,
- supports_check_mode=True)
-
- lines = module.params['lines']
- parents = module.params['parents'] or list()
+ match=dict(default='line', choices=['line', 'strict', 'exact', 'none']),
+ replace=dict(default='line', choices=['line', 'block']),
- before = module.params['before']
- after = module.params['after']
+ update=dict(choices=['merge', 'check'], default='merge'),
+ backup=dict(type='bool', default=False),
- match = module.params['match']
- replace = module.params['replace']
+ config=dict(),
+ default=dict(type='bool', default=False),
- if not module.params['force']:
- contents = get_config(module)
- config = NetworkConfig(contents=contents, indent=1)
+ save=dict(type='bool', default=False),
+ )
- candidate = NetworkConfig(indent=1)
- candidate.add(lines, parents=parents)
+ mutually_exclusive = [('lines', 'src')]
- commands = candidate.difference(config, path=parents, match=match, replace=replace)
- else:
- commands = parents
- commands.extend(lines)
+ module = NetworkModule(argument_spec=argument_spec,
+ connect_on_load=False,
+ mutually_exclusive=mutually_exclusive,
+ supports_check_mode=True)
- result = dict(changed=False)
+ warnings = list()
+ check_args(module, warnings)
- if commands:
- if before:
- commands[:0] = before
+ result = dict(changed=False, warnings=warnings)
- if after:
- commands.extend(after)
+ if module.params['backup']:
+ result['__backup__'] = module.config.get_config()
- if not module.check_mode:
- commands = [str(c).strip() for c in commands]
- response = module.configure(commands)
- result['responses'] = response
- result['changed'] = True
+ try:
+ run(module, result)
+ except NetworkError:
+ exc = get_exception()
+ module.fail_json(msg=str(exc))
- result['updates'] = commands
module.exit_json(**result)
-from ansible.module_utils.basic import *
-from ansible.module_utils.shell import *
-from ansible.module_utils.netcfg import *
-from ansible.module_utils.asa import *
if __name__ == '__main__':
main()