refactor arguments in ops_template

This commit refactors the arugments used in ops_template to be strictly
typed and handle by declarative / rest and cli based configurations.  It
also removes old arguments not supported and cleans up the documentation
strings
This commit is contained in:
Peter Sprygada 2016-02-28 11:28:18 -05:00
parent edf3aa336f
commit b3f232434a

View file

@ -17,10 +17,10 @@
# #
DOCUMENTATION = """ DOCUMENTATION = """
--- ---
module: ops_config module: ops_template
version_added: "2.1" version_added: "2.1"
author: "Peter Sprygada (@privateip)" author: "Peter Sprygada (@privateip)"
short_description: Push configuration to OpenSwitch using declarative config short_description: Push configuration to OpenSwitch
description: description:
- The OpenSwitch platform provides a library for pushing JSON structured - The OpenSwitch platform provides a library for pushing JSON structured
configuration files into the current running-config. This module configuration files into the current running-config. This module
@ -36,8 +36,7 @@ options:
file with config or a template that will be merged during file with config or a template that will be merged during
runtime. By default the task will search for the source runtime. By default the task will search for the source
file in role or playbook root folder in templates directory. file in role or playbook root folder in templates directory.
required: false required: true
default: null
force: force:
description: description:
- The force argument instructs the module to not consider the - The force argument instructs the module to not consider the
@ -46,45 +45,16 @@ options:
without first checking if already configured. without first checking if already configured.
required: false required: false
default: false default: false
choices: BOOLEANS choices: ['yes', 'no']
include_defaults:
description:
- The module, by default, will collect the current device
running-config to use as a base for comparision to the commands
in I(src). Setting this value to true will cause the module
to issue the command `show running-config all` to include all
device settings.
required: false
default: false
choices: BOOLEANS
backup: backup:
description: description:
- When this argument is configured true, the module will backup - When this argument is configured true, the module will backup
the running-config from the node prior to making any changes. the running-config from the node prior to making any changes.
The backup file will be written to backup_{{ hostname }} in The backup file will be written to backups/ in
the root of the playbook directory. the root of the playbook directory.
required: false required: false
default: false default: false
choices: BOOLEANS choices: ['yes', 'no']
ignore_missing:
description:
- This flag instructs the module to ignore lines that are missing
from the device configuration. In some instances, the config
command doesn't show up in the running-config because it is the
default. See examples for how this is used.
required: false
default: false
choices: BOOLEANS
replace:
description:
- This argument will cause the provided configuration to be replaced
on the destination node. The use of the replace argument will
always cause the task to set changed to true and will implies
I(force) is true. This argument is only valid with I(transport)
is eapi.
required: false
default: false
choice: BOOLEANS
config: config:
description: description:
- The module, by default, will connect to the remote device and - The module, by default, will connect to the remote device and
@ -99,38 +69,39 @@ options:
""" """
EXAMPLES = """ EXAMPLES = """
# Pushes the candidate configuraition to the device using a variable - name: set hostname with file lookup
ops_template:
src: ./hostname.json
backup: yes
remote_user: admin
become: yes
vars: - name: set hostname with var
config: ops_template:
System
hostname: ops01
tasks:
- ops_config:
src: "{{ config }}" src: "{{ config }}"
remote_user: admin
# Reads the candidate configuration from a file become: yes
tasks:
- ops_config:
src: "{{ lookup('file', 'ops_config.json') }}"
""" """
RETURN = """ RETURN = """
updates: updates:
description: The list of configuration updates to be merged description: The list of configuration updates to be merged
retured: always retured: always
type: dict
sample: {obj, obj}
responses:
desription: returns the responses when configuring using cli
returned: when transport == cli
type: list type: list
sample: ["System.hostname: ops01 (switch)"] sample: [...]
""" """
import copy
def compare(this, other, ignore_missing=False): def compare(this, other):
parents = [item.text for item in this.parents] parents = [item.text for item in this.parents]
for entry in other: for entry in other:
if this == entry: if this == entry:
return None return None
if not ignore_missing:
return this return this
def expand(obj, queue): def expand(obj, queue):
@ -197,11 +168,10 @@ def main():
""" """
argument_spec = dict( argument_spec = dict(
src=dict(), src=dict(type='dict'),
force=dict(default=False, type='bool'), force=dict(default=False, type='bool'),
backup=dict(default=False, type='bool'), backup=dict(default=False, type='bool'),
ignore_missing=dict(default=False, type='bool'), config=dict(type='dict'),
config=dict(),
) )
mutually_exclusive = [('config', 'backup'), ('config', 'force')] mutually_exclusive = [('config', 'backup'), ('config', 'force')]
@ -211,33 +181,22 @@ def main():
supports_check_mode=True) supports_check_mode=True)
src = module.params['src'] src = module.params['src']
force = module.params['force']
backup = module.params['backup']
ignore_missing = module.params['ignore_missing']
config = module.params['config']
result = dict(changed=False) result = dict(changed=False)
contents = get_config(module)
result['_backup'] = copy.deepcopy(module.config)
if module.params['transport'] in ['ssh', 'rest']: if module.params['transport'] in ['ssh', 'rest']:
if isinstance(src, basestring): config = contents
src = module.from_json(src)
if not force:
config = module.config
else:
config = dict()
if backup:
result['_config'] = module.config
changeset = diff(src, config) changeset = diff(src, config)
candidate = merge(changeset, config) candidate = merge(changeset, config)
updates = list() updates = dict()
for path, key, new_value, old_value in changeset: for path, key, new_value, old_value in changeset:
update = '%s.%s' % ('.'.join(path), key) path = '%s.%s' % ('.'.join(path), key)
update += ': %s (%s)' % (new_value, old_value) updates[path] = new_value
updates.append(update)
result['updates'] = updates result['updates'] = updates
if changeset: if changeset:
@ -246,13 +205,9 @@ def main():
result['changed'] = True result['changed'] = True
else: else:
config = module.parse_config(config)
candidate = module.parse_config(module.params['src']) candidate = module.parse_config(module.params['src'])
contents = get_config(module)
result['_config'] = module.config
config = module.parse_config(contents)
commands = collections.OrderedDict() commands = collections.OrderedDict()
toplevel = [c.text for c in config] toplevel = [c.text for c in config]
@ -264,7 +219,7 @@ def main():
if line.text not in toplevel: if line.text not in toplevel:
expand(line, commands) expand(line, commands)
else: else:
item = compare(line, config, ignore_missing) item = compare(line, config)
if item: if item:
expand(item, commands) expand(item, commands)
@ -274,9 +229,9 @@ def main():
if not module.check_mode: if not module.check_mode:
commands = [str(c).strip() for c in commands] commands = [str(c).strip() for c in commands]
response = module.configure(commands) response = module.configure(commands)
result['responses'] = response
result['changed'] = True result['changed'] = True
result['updates'] = commands
result['commands'] = commands
module.exit_json(**result) module.exit_json(**result)