mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add aggregate functionality to eos_vrf (#27915)
* Add aggregate functionality to eos_vrf * Add tests for eos_vrf aggregate option * Remove test2 and test3 vrfs at the beginning of the eos_vrf tests * Pull all vrfs With aggregate, we need to get all VRFs and we then compare with desired VRFs, instead of assuming it will be just one.
This commit is contained in:
parent
eee09565b1
commit
7e2169f6d5
2 changed files with 188 additions and 54 deletions
|
@ -81,100 +81,152 @@ import re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def search_obj_in_list(name, lst):
|
||||||
|
for o in lst:
|
||||||
|
if o['name'] == name:
|
||||||
|
return o
|
||||||
|
|
||||||
|
|
||||||
def map_obj_to_commands(updates, module):
|
def map_obj_to_commands(updates, module):
|
||||||
commands = list()
|
commands = list()
|
||||||
want, have = updates
|
want, have = updates
|
||||||
state = module.params['state']
|
state = module.params['state']
|
||||||
|
|
||||||
|
for w in want:
|
||||||
|
name = w['name']
|
||||||
|
rd = w['rd']
|
||||||
|
interfaces = w['interfaces']
|
||||||
|
|
||||||
|
obj_in_have = search_obj_in_list(name, have)
|
||||||
|
|
||||||
if state == 'absent':
|
if state == 'absent':
|
||||||
if have:
|
if have:
|
||||||
commands.append('no vrf definition %s' % want['name'])
|
commands.append('no vrf definition %s' % name)
|
||||||
elif state == 'present':
|
elif state == 'present':
|
||||||
if not have:
|
if not obj_in_have:
|
||||||
commands.append('vrf definition %s' % want['name'])
|
commands.append('vrf definition %s' % name)
|
||||||
|
|
||||||
if want['rd'] is not None:
|
if rd is not None:
|
||||||
commands.append('rd %s' % want['rd'])
|
commands.append('rd %s' % rd)
|
||||||
|
|
||||||
if want['interfaces']:
|
if w['interfaces']:
|
||||||
for i in want['interfaces']:
|
for i in w['interfaces']:
|
||||||
commands.append('interface %s' % i)
|
commands.append('interface %s' % i)
|
||||||
commands.append('vrf forwarding %s' % want['name'])
|
commands.append('vrf forwarding %s' % w['name'])
|
||||||
else:
|
else:
|
||||||
if want['rd'] is not None and want['rd'] != have['rd']:
|
if w['rd'] is not None and w['rd'] != obj_in_have['rd']:
|
||||||
commands.append('vrf definition %s' % want['name'])
|
commands.append('vrf definition %s' % w['name'])
|
||||||
commands.append('rd %s' % want['rd'])
|
commands.append('rd %s' % w['rd'])
|
||||||
|
|
||||||
if want['interfaces']:
|
if w['interfaces']:
|
||||||
if not have['interfaces']:
|
if not obj_in_have['interfaces']:
|
||||||
for i in want['interfaces']:
|
for i in w['interfaces']:
|
||||||
commands.append('interface %s' % i)
|
commands.append('interface %s' % i)
|
||||||
commands.append('vrf forwarding %s' % want['name'])
|
commands.append('vrf forwarding %s' % w['name'])
|
||||||
elif set(want['interfaces']) != have['interfaces']:
|
elif set(w['interfaces']) != obj_in_have['interfaces']:
|
||||||
missing_interfaces = list(set(want['interfaces']) - set(have['interfaces']))
|
missing_interfaces = list(set(w['interfaces']) - set(obj_in_have['interfaces']))
|
||||||
|
|
||||||
for i in missing_interfaces:
|
for i in missing_interfaces:
|
||||||
commands.append('interface %s' % i)
|
commands.append('interface %s' % i)
|
||||||
commands.append('vrf forwarding %s' % want['name'])
|
commands.append('vrf forwarding %s' % w['name'])
|
||||||
|
|
||||||
return commands
|
return commands
|
||||||
|
|
||||||
|
|
||||||
def map_config_to_obj(module):
|
def map_config_to_obj(module):
|
||||||
obj = {}
|
objs = []
|
||||||
output = run_commands(module, ['show vrf %s' % module.params['name']])
|
output = run_commands(module, ['show vrf'])
|
||||||
lines = output[0].strip().splitlines()
|
lines = output[0].strip().splitlines()[2:]
|
||||||
|
|
||||||
if len(lines) > 2:
|
for l in lines:
|
||||||
splitted_line = re.split(r'\s{2,}', lines[2].strip())
|
if not l:
|
||||||
|
continue
|
||||||
|
|
||||||
|
splitted_line = re.split(r'\s{2,}', l.strip())
|
||||||
|
|
||||||
|
if len(splitted_line) == 1:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
obj = {}
|
||||||
obj['name'] = splitted_line[0]
|
obj['name'] = splitted_line[0]
|
||||||
obj['rd'] = splitted_line[1]
|
obj['rd'] = splitted_line[1]
|
||||||
obj['interfaces'] = None
|
obj['interfaces'] = None
|
||||||
|
|
||||||
if len(splitted_line) > 4:
|
if len(splitted_line) > 4:
|
||||||
obj['interfaces'] = []
|
obj['interfaces'] = []
|
||||||
|
|
||||||
for i in splitted_line[4].split(','):
|
for i in splitted_line[4].split(','):
|
||||||
obj['interfaces'].append(i.strip())
|
obj['interfaces'].append(i.strip())
|
||||||
|
|
||||||
return obj
|
objs.append(obj)
|
||||||
|
|
||||||
|
return objs
|
||||||
|
|
||||||
|
|
||||||
def map_params_to_obj(module):
|
def map_params_to_obj(module):
|
||||||
return {
|
obj = []
|
||||||
|
|
||||||
|
if 'aggregate' in module.params and module.params['aggregate']:
|
||||||
|
for c in module.params['aggregate']:
|
||||||
|
d = c.copy()
|
||||||
|
|
||||||
|
if 'state' not in d:
|
||||||
|
d['state'] = module.params['state']
|
||||||
|
if 'rd' not in d:
|
||||||
|
d['rd'] = module.params['rd']
|
||||||
|
if 'interfaces' not in d:
|
||||||
|
d['interfaces'] = module.params['interfaces']
|
||||||
|
|
||||||
|
obj.append(d)
|
||||||
|
else:
|
||||||
|
name = module.params['name'],
|
||||||
|
state = module.params['state'],
|
||||||
|
rd = module.params['rd'],
|
||||||
|
interfaces = module.params['interfaces']
|
||||||
|
|
||||||
|
obj.append({
|
||||||
'name': module.params['name'],
|
'name': module.params['name'],
|
||||||
'state': module.params['state'],
|
'state': module.params['state'],
|
||||||
'rd': module.params['rd'],
|
'rd': module.params['rd'],
|
||||||
'interfaces': module.params['interfaces']
|
'interfaces': module.params['interfaces']
|
||||||
}
|
})
|
||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
def check_declarative_intent_params(module):
|
def check_declarative_intent_params(want, module):
|
||||||
if module.params['interfaces']:
|
if module.params['interfaces']:
|
||||||
time.sleep(module.params['delay'])
|
time.sleep(module.params['delay'])
|
||||||
have = map_config_to_obj(module)
|
have = map_config_to_obj(module)
|
||||||
vrf = module.params['name']
|
|
||||||
|
|
||||||
for i in module.params['interfaces']:
|
for w in want:
|
||||||
if i not in have['interfaces']:
|
for i in w['interfaces']:
|
||||||
module.fail_json(msg="Interface %s not configured on vrf %s" % (i, vrf))
|
obj_in_have = search_obj_in_list(w['name'], have)
|
||||||
|
|
||||||
|
if obj_in_have and 'interfaces' in obj_in_have and i not in obj_in_have['interfaces']:
|
||||||
|
module.fail_json(msg="Interface %s not configured on vrf %s" % (i, w['name']))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
""" main entry point for module execution
|
""" main entry point for module execution
|
||||||
"""
|
"""
|
||||||
argument_spec = dict(
|
argument_spec = dict(
|
||||||
name=dict(required=True),
|
name=dict(),
|
||||||
interfaces=dict(type='list'),
|
interfaces=dict(type='list'),
|
||||||
delay=dict(default=10, type='int'),
|
delay=dict(default=10, type='int'),
|
||||||
rd=dict(),
|
rd=dict(),
|
||||||
aggregate=dict(),
|
aggregate=dict(type='list'),
|
||||||
purge=dict(default=False, type='bool'),
|
purge=dict(default=False, type='bool'),
|
||||||
state=dict(default='present', choices=['present', 'absent'])
|
state=dict(default='present', choices=['present', 'absent'])
|
||||||
)
|
)
|
||||||
|
|
||||||
argument_spec.update(eos_argument_spec)
|
argument_spec.update(eos_argument_spec)
|
||||||
|
|
||||||
|
required_one_of = [['name', 'aggregate']]
|
||||||
|
mutually_exclusive = [['name', 'aggregate']]
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
|
required_one_of=required_one_of,
|
||||||
|
mutually_exclusive=mutually_exclusive,
|
||||||
supports_check_mode=True)
|
supports_check_mode=True)
|
||||||
|
|
||||||
warnings = list()
|
warnings = list()
|
||||||
|
@ -200,7 +252,7 @@ def main():
|
||||||
result['changed'] = True
|
result['changed'] = True
|
||||||
|
|
||||||
if result['changed']:
|
if result['changed']:
|
||||||
check_declarative_intent_params(module)
|
check_declarative_intent_params(want, module)
|
||||||
|
|
||||||
module.exit_json(**result)
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,20 @@
|
||||||
authorize: yes
|
authorize: yes
|
||||||
provider: "{{ cli }}"
|
provider: "{{ cli }}"
|
||||||
|
|
||||||
|
- name: setup - remove vrf
|
||||||
|
eos_vrf:
|
||||||
|
name: test2
|
||||||
|
state: absent
|
||||||
|
authorize: yes
|
||||||
|
provider: "{{ cli }}"
|
||||||
|
|
||||||
|
- name: setup - remove vrf
|
||||||
|
eos_vrf:
|
||||||
|
name: test3
|
||||||
|
state: absent
|
||||||
|
authorize: yes
|
||||||
|
provider: "{{ cli }}"
|
||||||
|
|
||||||
- name: Create vrf
|
- name: Create vrf
|
||||||
eos_vrf:
|
eos_vrf:
|
||||||
name: test
|
name: test
|
||||||
|
@ -110,6 +124,74 @@
|
||||||
# Ensure sessions contains epoc. Will fail after 18th May 2033
|
# Ensure sessions contains epoc. Will fail after 18th May 2033
|
||||||
- "'session_name' not in result.commands"
|
- "'session_name' not in result.commands"
|
||||||
|
|
||||||
|
- name: Create aggregate of VRFs
|
||||||
|
eos_vrf:
|
||||||
|
aggregate:
|
||||||
|
- { name: test2, rd: "1:202" }
|
||||||
|
- { name: test3, rd: "1:203" }
|
||||||
|
state: present
|
||||||
|
authorize: yes
|
||||||
|
provider: "{{ cli }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.changed == true"
|
||||||
|
- "'vrf definition test2' in result.commands"
|
||||||
|
- "'rd 1:202' in result.commands"
|
||||||
|
- "'vrf definition test3' in result.commands"
|
||||||
|
- "'rd 1:203' in result.commands"
|
||||||
|
# Ensure sessions contains epoc. Will fail after 18th May 2033
|
||||||
|
- "'ansible_1' in result.session_name"
|
||||||
|
|
||||||
|
- name: Create aggregate of VRFs again (idempotent)
|
||||||
|
eos_vrf:
|
||||||
|
aggregate:
|
||||||
|
- { name: test2, rd: "1:202" }
|
||||||
|
- { name: test3, rd: "1:203" }
|
||||||
|
state: present
|
||||||
|
authorize: yes
|
||||||
|
provider: "{{ cli }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.changed == false"
|
||||||
|
- "result.commands | length == 0"
|
||||||
|
# Ensure sessions contains epoc. Will fail after 18th May 2033
|
||||||
|
- "result.session_name is not defined"
|
||||||
|
|
||||||
|
- name: Delete VRFs
|
||||||
|
eos_vrf:
|
||||||
|
name: test
|
||||||
|
state: absent
|
||||||
|
authorize: yes
|
||||||
|
provider: "{{ cli }}"
|
||||||
|
|
||||||
|
- name: Delete VRFs again (idempotent)
|
||||||
|
eos_vrf:
|
||||||
|
name: test
|
||||||
|
state: absent
|
||||||
|
authorize: yes
|
||||||
|
provider: "{{ cli }}"
|
||||||
|
|
||||||
|
- name: Delete aggregate of VRFs
|
||||||
|
eos_vrf:
|
||||||
|
aggregate:
|
||||||
|
- { name: test2 }
|
||||||
|
- { name: test3 }
|
||||||
|
state: absent
|
||||||
|
authorize: yes
|
||||||
|
provider: "{{ cli }}"
|
||||||
|
|
||||||
|
- name: Delete VRFs again (idempotent)
|
||||||
|
eos_vrf:
|
||||||
|
aggregate:
|
||||||
|
- { name: test2 }
|
||||||
|
- { name: test3 }
|
||||||
|
state: absent
|
||||||
|
authorize: yes
|
||||||
|
provider: "{{ cli }}"
|
||||||
|
|
||||||
# FIXME add in tests for everything defined in docs
|
# FIXME add in tests for everything defined in docs
|
||||||
# FIXME Test state:absent + test:
|
# FIXME Test state:absent + test:
|
||||||
|
|
Loading…
Reference in a new issue