summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDag Wieers <dag@wieers.com>2019-01-26 03:48:13 +0100
committerGitHub <noreply@github.com>2019-01-26 03:48:13 +0100
commit73636175da5f44eff2d2ac9623e38ed35d6e6309 (patch)
treedece69402823c521d4d7fda3f12dd4033f66ab7a
parent2c2a79f7129595ae0dda0fa7a1d457f3c8ce05f7 (diff)
downloadansible-73636175da5f44eff2d2ac9623e38ed35d6e6309.tar.gz
MSO: Refactor modules to common structure (#51354)
This PR includes: - Various fixes to jsonpatch interface - Added seealso: and notes: to docs - Various improvements to docs - A set of bugfixes found during integration tests Full integration tests follow.
-rw-r--r--lib/ansible/modules/network/aci/mso_schema.py2
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_site.py14
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template.py74
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_anp.py9
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_anp_epg.py32
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_anp_epg_subnet.py47
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_bd.py40
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_bd_subnet.py44
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_contract_filter.py26
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_externalepg.py32
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_filter_entry.py84
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_l3out.py34
-rw-r--r--lib/ansible/modules/network/aci/mso_schema_template_vrf.py36
13 files changed, 208 insertions, 266 deletions
diff --git a/lib/ansible/modules/network/aci/mso_schema.py b/lib/ansible/modules/network/aci/mso_schema.py
index 1026ea7f21..ba2afe8ada 100644
--- a/lib/ansible/modules/network/aci/mso_schema.py
+++ b/lib/ansible/modules/network/aci/mso_schema.py
@@ -48,7 +48,7 @@ options:
choices: [ absent, present, query ]
default: present
notes:
-- This module cannot create empty schemas (i.e. schemas without templates).
+- Due to restrictions of the MSO REST API this module cannot create empty schemas (i.e. schemas without templates).
Use the M(mso_schema_template) to automatically create schemas with templates.
seealso:
- module: mso_schema_site
diff --git a/lib/ansible/modules/network/aci/mso_schema_site.py b/lib/ansible/modules/network/aci/mso_schema_site.py
index 676b51181a..1c5e2859f6 100644
--- a/lib/ansible/modules/network/aci/mso_schema_site.py
+++ b/lib/ansible/modules/network/aci/mso_schema_site.py
@@ -135,7 +135,6 @@ def main():
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
# Schema exists
- schema_id = schema_obj['id']
schema_path = 'schemas/{id}'.format(**schema_obj)
# Get site
@@ -159,16 +158,16 @@ def main():
mso.existing = []
mso.exit_json()
+ sites_path = '/sites'
+ site_path = '/sites/{0}'.format(site)
ops = []
mso.previous = mso.existing
if state == 'absent':
- mso.proposed = mso.sent = {}
-
if mso.existing:
# Remove existing site
- mso.existing = {}
- ops.append(dict(op='remove', path='/sites/{0}'.format(site_idx)))
+ mso.sent = mso.existing = {}
+ ops.append(dict(op='remove', path=site_path))
elif state == 'present':
if not mso.existing:
@@ -187,8 +186,9 @@ def main():
mso.sanitize(payload, collate=True)
- mso.existing = mso.proposed = mso.sent
- ops.append(dict(op='add', path='/sites/-', value=mso.sent))
+ ops.append(dict(op='add', path=sites_path + '/-', value=mso.sent))
+
+ mso.existing = mso.proposed
if not module.check_mode:
mso.request(schema_path, method='PATCH', data=ops)
diff --git a/lib/ansible/modules/network/aci/mso_schema_template.py b/lib/ansible/modules/network/aci/mso_schema_template.py
index e77ef837de..3f337102ca 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template.py
@@ -21,6 +21,11 @@ author:
- Dag Wieers (@dagwieers)
version_added: '2.8'
options:
+ tenant:
+ description:
+ - The tenant used for this template.
+ type: str
+ required: yes
schema:
description:
- The name of the schema.
@@ -31,10 +36,6 @@ options:
- The name of the template.
type: str
aliases: [ name ]
- tenant:
- description:
- - The tenant used for this template.
- type: str
display_name:
description:
- The name as displayed on the MSO web interface.
@@ -47,7 +48,7 @@ options:
choices: [ absent, present, query ]
default: present
notes:
-- This module creates schemas when needed, and removes them when the last template has been removed.
+- Due to restrictions of the MSO REST API this module creates schemas when needed, and removes them when the last template has been removed.
seealso:
- module: mso_schema
- module: mso_schema_site
@@ -137,30 +138,34 @@ def main():
# Get schema
schema_obj = mso.get_obj('schemas', displayName=schema)
+
+ mso.existing = {}
if schema_obj:
# Schema exists
- path = 'schemas/{id}'.format(**schema_obj)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
- if template is None:
- mso.existing = schema_obj['templates']
- elif template in templates:
- template_idx = templates.index(template)
- mso.existing = schema_obj['templates'][template_idx]
+ if template:
+ if template in templates:
+ template_idx = templates.index(template)
+ mso.existing = schema_obj['templates'][template_idx]
else:
- mso.existing = {}
+ mso.existing = schema_obj['templates']
else:
- path = 'schemas'
-
- if template is None:
- mso.existing = []
- else:
- mso.existing = {}
+ schema_path = 'schemas'
if state == 'query':
+ if not mso.existing:
+ if template:
+ mso.fail_json(msg="Template '{0}' not found".format(template))
+ else:
+ mso.existing = []
mso.exit_json()
+ template_path = '/templates/{0}'.format(template)
+ ops = []
+
mso.previous = mso.existing
if state == 'absent':
mso.proposed = mso.sent = {}
@@ -172,15 +177,11 @@ def main():
# There is only one tenant, remove schema
mso.existing = {}
if not module.check_mode:
- mso.request(path, method='DELETE')
+ mso.request(schema_path, method='DELETE')
elif mso.existing:
# Remove existing template
mso.existing = {}
- operation = [
- dict(op='remove', path='/templates/{template}'.format(template=template)),
- ]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+ ops.append(dict(op='remove', path=template_path))
else:
# There was no template to begin with
pass
@@ -206,7 +207,7 @@ def main():
mso.existing = payload['templates'][0]
if not module.check_mode:
- mso.request(path, method='POST', data=payload)
+ mso.request(schema_path, method='POST', data=payload)
elif mso.existing:
# Template exists, so we have to update it
@@ -218,14 +219,10 @@ def main():
mso.sanitize(payload, collate=True)
- mso.existing = payload
- operations = [
- dict(op='replace', path='/templates/{template}/displayName'.format(template=template), value=display_name),
- dict(op='replace', path='/templates/{template}/tenantId'.format(template=template), value=tenant_id),
- ]
+ ops.append(dict(op='replace', path=template_path + '/displayName', value=display_name))
+ ops.append(dict(op='replace', path=template_path + '/tenantId', value=tenant_id))
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operations)
+ mso.existing = mso.proposed
else:
# Template does not exist, so we have to add it
payload = dict(
@@ -234,13 +231,14 @@ def main():
tenantId=tenant_id,
)
- mso.existing = payload
- operations = [
- dict(op='add', path='/templates/-', value=payload),
- ]
+ mso.sanitize(payload, collate=True)
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operations)
+ ops.append(dict(op='add', path='/templates/-', value=payload))
+
+ mso.existing = mso.proposed
+
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_anp.py b/lib/ansible/modules/network/aci/mso_schema_template_anp.py
index 87c53917db..975c01c143 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_anp.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_anp.py
@@ -30,6 +30,7 @@ options:
description:
- The name of the template.
type: list
+ required: yes
anp:
description:
- The name of the ANP to manage.
@@ -134,12 +135,10 @@ def main():
# Get schema_id
schema_obj = mso.get_obj('schemas', displayName=schema)
- if schema_obj:
- schema_id = schema_obj['id']
- else:
+ if not schema_obj:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -197,7 +196,7 @@ def main():
mso.existing = mso.proposed
if not module.check_mode:
- mso.request(path, method='PATCH', data=ops)
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_anp_epg.py b/lib/ansible/modules/network/aci/mso_schema_template_anp_epg.py
index b9b9c83b54..f6a8fc3351 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_anp_epg.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_anp_epg.py
@@ -30,10 +30,12 @@ options:
description:
- The name of the template to change.
type: list
+ required: yes
anp:
description:
- The name of the ANP.
type: str
+ required: yes
epg:
description:
- The name of the EPG to manage.
@@ -231,7 +233,7 @@ def main():
else:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -258,16 +260,15 @@ def main():
mso.fail_json(msg="EPG '{epg}' not found".format(epg=epg))
mso.exit_json()
+ epgs_path = '/templates/{0}/anps/{1}/epgs'.format(template, anp)
+ epg_path = '/templates/{0}/anps/{1}/epgs/{2}'.format(template, anp, epg)
+ ops = []
+
mso.previous = mso.existing
if state == 'absent':
if mso.existing:
mso.sent = mso.existing = {}
- operation = [dict(
- op='remove',
- path='/templates/{template}/anps/{anp}/epgs/{epg}'.format(template=template, anp=anp, epg=epg),
- )]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+ ops.append(dict(op='remove', path=epg_path))
elif state == 'present':
bd_ref = mso.make_reference(bd, 'bd', schema_id, template)
@@ -292,21 +293,14 @@ def main():
mso.sanitize(payload, collate=True)
if mso.existing:
- operation = [dict(
- op='replace',
- path='/templates/{template}/anps/{anp}/epgs/{epg}'.format(template=template, anp=anp, epg=epg),
- value=mso.sent,
- )]
+ ops.append(dict(op='replace', path=epg_path, value=mso.sent))
else:
- operation = [dict(
- op='add',
- path='/templates/{template}/anps/{anp}/epgs/-'.format(template=template, anp=anp),
- value=mso.sent,
- )]
+ ops.append(dict(op='add', path=epgs_path + '/-', value=mso.sent))
mso.existing = mso.proposed
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_anp_epg_subnet.py b/lib/ansible/modules/network/aci/mso_schema_template_anp_epg_subnet.py
index 5fbcc300db..bfa4196ec3 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_anp_epg_subnet.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_anp_epg_subnet.py
@@ -30,14 +30,17 @@ options:
description:
- The name of the template to change.
type: list
+ required: yes
anp:
description:
- The name of the ANP.
type: str
+ required: yes
epg:
description:
- The name of the EPG to manage.
type: str
+ required: yes
ip:
description:
- The IP range in CIDR notation.
@@ -67,6 +70,8 @@ options:
type: str
choices: [ absent, present, query ]
default: present
+notes:
+- Due to restrictions of the MSO REST API concurrent modifications to EPG subnets can be dangerous and corrupt data.
extends_documentation_fragment: mso
'''
@@ -164,14 +169,12 @@ def main():
mso = MSOModule(module)
- # Get schema_id
+ # Get schema
schema_obj = mso.get_obj('schemas', displayName=schema)
- if schema_obj:
- schema_id = schema_obj['id']
- else:
+ if not schema_obj:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -196,7 +199,8 @@ def main():
subnets = [s['ip'] for s in schema_obj['templates'][template_idx]['anps'][anp_idx]['epgs'][epg_idx]['subnets']]
if ip in subnets:
ip_idx = subnets.index(ip)
- # FIXME: Forced to use index here
+ # FIXME: Changes based on index are DANGEROUS
+ subnet_path = '/templates/{0}/anps/{1}/epgs/{2}/subnets/{3}'.format(template, anp, epg, ip_idx)
mso.existing = schema_obj['templates'][template_idx]['anps'][anp_idx]['epgs'][epg_idx]['subnets'][ip_idx]
if state == 'query':
@@ -206,17 +210,14 @@ def main():
mso.fail_json(msg="Subnet '{ip}' not found".format(ip=ip))
mso.exit_json()
+ subnets_path = '/templates/{0}/anps/{1}/epgs/{2}/subnets'.format(template, anp, epg)
+ ops = []
+
mso.previous = mso.existing
if state == 'absent':
if mso.existing:
- mso.sent = mso.existing = {}
- operation = [dict(
- op='remove',
- # FIXME: Forced to use index here
- path='/templates/{template}/anps/{anp}/epgs/{epg}/subnets/{ip}'.format(template=template, anp=anp, epg=epg, ip=ip_idx),
- )]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+ mso.existing = {}
+ ops.append(dict(op='remove', path=subnet_path))
elif state == 'present':
if description is None and not mso.existing:
@@ -239,22 +240,14 @@ def main():
mso.sanitize(payload, collate=True)
if mso.existing:
- operation = [dict(
- op='replace',
- # FIXME: Forced to use index here
- path='/templates/{template}/anps/{anp}/epgs/{epg}/subnets/{ip}'.format(template=template, anp=anp, epg=epg, ip=ip_idx),
- value=mso.sent,
- )]
+ ops.append(dict(op='replace', path=subnet_path, value=mso.sent))
else:
- operation = [dict(
- op='add',
- path='/templates/{template}/anps/{anp}/epgs/{epg}/subnets/-'.format(template=template, anp=anp, epg=epg),
- value=mso.sent,
- )]
+ ops.append(dict(op='add', path=subnets_path + '/-', value=mso.sent))
mso.existing = mso.proposed
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_bd.py b/lib/ansible/modules/network/aci/mso_schema_template_bd.py
index dddc6f5d49..57b01922e4 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_bd.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_bd.py
@@ -30,6 +30,7 @@ options:
description:
- The name of the template.
type: list
+ required: yes
bd:
description:
- The name of the BD to manage.
@@ -41,11 +42,11 @@ options:
type: str
vrf:
description:
- - The VRF associated to this ANP.
+ - The VRF associated to this BD.
type: str
subnets:
description:
- - The subnets associated to this ANP.
+ - The subnets associated to this BD.
type: list
suboptions:
ip:
@@ -203,7 +204,7 @@ def main():
else:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -225,16 +226,15 @@ def main():
mso.fail_json(msg="BD '{bd}' not found".format(bd=bd))
mso.exit_json()
+ bds_path = '/templates/{0}/bds'.format(template)
+ bd_path = '/templates/{0}/bds/{1}'.format(template, bd)
+ ops = []
+
mso.previous = mso.existing
if state == 'absent':
if mso.existing:
mso.sent = mso.existing = {}
- operation = [dict(
- op='remove',
- path='/templates/{template}/bds/{bd}'.format(template=template, bd=bd),
- )]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+ ops.append(dict(op='remove', path=bd_path))
elif state == 'present':
vrf_ref = mso.make_reference(vrf, 'vrf', schema_id, template)
@@ -242,6 +242,8 @@ def main():
if display_name is None and not mso.existing:
display_name = bd
+ if subnets is None and not mso.existing:
+ subnets = []
payload = dict(
name=bd,
@@ -255,25 +257,17 @@ def main():
vrfRef=vrf_ref,
)
- mso.sanitize(payload, collate=True, unwanted=['bdRef', 'vrfRef'])
+ mso.sanitize(payload, collate=True)
if mso.existing:
- operation = [dict(
- op='replace',
- path='/templates/{template}/bds/{bd}'.format(template=template, bd=bd),
- value=mso.sent,
- )]
-
+ ops.append(dict(op='replace', path=bd_path, value=mso.sent))
else:
- operation = [dict(
- op='add',
- path='/templates/{template}/bds/-'.format(template=template),
- value=mso.sent,
- )]
+ ops.append(dict(op='add', path=bds_path + '/-', value=mso.sent))
mso.existing = mso.proposed
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_bd_subnet.py b/lib/ansible/modules/network/aci/mso_schema_template_bd_subnet.py
index 314fcf5df5..8751bf87f7 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_bd_subnet.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_bd_subnet.py
@@ -30,10 +30,12 @@ options:
description:
- The name of the template to change.
type: list
+ required: yes
bd:
description:
- The name of the BD to manage.
type: str
+ required: yes
ip:
description:
- The IP range in CIDR notation.
@@ -63,6 +65,8 @@ options:
type: str
choices: [ absent, present, query ]
default: present
+notes:
+- Due to restrictions of the MSO REST API concurrent modifications to BD subnets can be dangerous and corrupt data.
extends_documentation_fragment: mso
'''
@@ -155,14 +159,12 @@ def main():
mso = MSOModule(module)
- # Get schema_id
+ # Get schema
schema_obj = mso.get_obj('schemas', displayName=schema)
- if schema_obj:
- schema_id = schema_obj['id']
- else:
+ if not schema_obj:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -180,7 +182,8 @@ def main():
subnets = [s['ip'] for s in schema_obj['templates'][template_idx]['bds'][bd_idx]['subnets']]
if ip in subnets:
ip_idx = subnets.index(ip)
- # FIXME: Forced to use index here
+ # FIXME: Changes based on index are DANGEROUS
+ subnet_path = '/templates/{0}/bds/{1}/subnets/{2}'.format(template, bd, ip_idx)
mso.existing = schema_obj['templates'][template_idx]['bds'][bd_idx]['subnets'][ip_idx]
if state == 'query':
@@ -190,17 +193,14 @@ def main():
mso.fail_json(msg="Subnet '{ip}' not found".format(ip=ip))
mso.exit_json()
+ subnets_path = '/templates/{0}/bds/{1}/subnets'.format(template, bd)
+ ops = []
+
mso.previous = mso.existing
if state == 'absent':
if mso.existing:
mso.sent = mso.existing = {}
- operation = [dict(
- op='remove',
- # FIXME: Forced to use index here
- path='/templates/{template}/bds/{bd}/subnets/{ip}'.format(template=template, bd=bd, ip=ip_idx),
- )]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+ ops.append(dict(op='remove', path=subnet_path))
elif state == 'present':
if description is None and not mso.existing:
@@ -223,22 +223,14 @@ def main():
mso.sanitize(payload, collate=True)
if mso.existing:
- operation = [dict(
- op='replace',
- # FIXME: Forced to use index here
- path='/templates/{template}/bds/{bd}/subnets/{ip}'.format(template=template, bd=bd, ip=ip_idx),
- value=mso.sent,
- )]
+ ops.append(dict(op='replace', path=subnet_path, value=mso.sent))
else:
- operation = [dict(
- op='add',
- path='/templates/{template}/bds/{bd}/subnets/-'.format(template=template, bd=bd),
- value=mso.sent,
- )]
+ ops.append(dict(op='add', path=subnets_path + '/-', value=mso.sent))
mso.existing = mso.proposed
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_contract_filter.py b/lib/ansible/modules/network/aci/mso_schema_template_contract_filter.py
index 53900e1edf..5584050b58 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_contract_filter.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_contract_filter.py
@@ -30,10 +30,12 @@ options:
description:
- The name of the template.
type: list
+ required: yes
contract:
description:
- The name of the contract to manage.
type: str
+ required: yes
contract_display_name:
description:
- The name as displayed on the MSO web interface.
@@ -78,6 +80,11 @@ options:
type: str
choices: [ absent, present, query ]
default: present
+seealso:
+- module: mso_schema_template_filter_entry
+notes:
+- Due to restrictions of the MSO REST API this module creates contracts when needed, and removes them when the last filter has been removed.
+- Due to restrictions of the MSO REST API concurrent modifications to contract filters can be dangerous and corrupt data.
extends_documentation_fragment: mso
'''
@@ -209,7 +216,7 @@ def main():
else:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -230,6 +237,8 @@ def main():
filter_ref = mso.filter_ref(filter_schema_id, filter_template, filter_name)
if filter_ref in filters:
filter_idx = filters.index(filter_ref)
+ # FIXME: Changes based on index are DANGEROUS
+ filter_path = '/templates/{0}/contracts/{1}/{2}/{3}'.format(template, contract, filter_key, filter_idx)
mso.existing = schema_obj['templates'][template_idx]['contracts'][contract_idx][filter_key][filter_idx]
if state == 'query':
@@ -244,8 +253,7 @@ def main():
ops = []
contract_path = '/templates/{0}/contracts/{1}'.format(template, contract)
- # FIXME: Removing based on index is DANGEROUS
- filter_path = '/templates/{0}/contracts/{1}/{2}/{3}'.format(template, contract, filter_key, filter_idx)
+ filters_path = '/templates/{0}/contracts/{1}/{2}'.format(template, contract, filter_key)
mso.previous = mso.existing
if state == 'absent':
@@ -266,9 +274,6 @@ def main():
mso.existing = {}
ops.append(dict(op='remove', path=filter_path))
- if not module.check_mode:
- mso.request(path, method='PATCH', data=ops)
-
elif state == 'present':
payload = dict(
@@ -282,11 +287,6 @@ def main():
mso.sanitize(payload, collate=True)
mso.existing = mso.sent
- ops = []
- contract_path = '/templates/{0}/contracts/{1}'.format(template, contract)
- filters_path = '/templates/{0}/contracts/{1}/{2}'.format(template, contract, filter_key)
- # FIXME: Updating based on index is DANGEROUS
- filter_path = '/templates/{0}/contracts/{1}/{2}/{3}'.format(template, contract, filter_key, filter_idx)
if contract_idx is None:
# COntract does not exist, so we have to create it
@@ -322,8 +322,8 @@ def main():
# Filter exists, we have to update it
ops.append(dict(op='replace', path=filter_path, value=mso.sent))
- if not module.check_mode:
- mso.request(path, method='PATCH', data=ops)
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_externalepg.py b/lib/ansible/modules/network/aci/mso_schema_template_externalepg.py
index 42537705c3..4ab53fe1f5 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_externalepg.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_externalepg.py
@@ -30,6 +30,7 @@ options:
description:
- The name of the template.
type: list
+ required: yes
externalepg:
description:
- The name of the external EPG to manage.
@@ -143,7 +144,7 @@ def main():
else:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -165,16 +166,15 @@ def main():
mso.fail_json(msg="External EPG '{externalepg}' not found".format(externalepg=externalepg))
mso.exit_json()
+ eepgs_path = '/templates/{0}/externalEpgs'.format(template)
+ eepg_path = '/templates/{0}/externalEpgs/{1}'.format(template, externalepg)
+ ops = []
+
mso.previous = mso.existing
if state == 'absent':
if mso.existing:
mso.sent = mso.existing = {}
- operation = [dict(
- op='remove',
- path='/templates/{template}/externalEpgs/{externalepg}'.format(template=template, externalepg=externalepg),
- )]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+ ops.append(dict(op='remove', path=eepg_path))
elif state == 'present':
vrf_ref = mso.make_reference(vrf, 'vrf', schema_id, template)
@@ -194,22 +194,14 @@ def main():
mso.sanitize(payload, collate=True)
if mso.existing:
- operation = [dict(
- op='replace',
- path='/templates/{template}/externalEpgs/{externalepg}'.format(template=template, externalepg=externalepg),
- value=mso.sent,
- )]
-
+ ops.append(dict(op='replace', path=eepg_path, value=mso.sent))
else:
- operation = [dict(
- op='add',
- path='/templates/{template}/externalEpgs/-'.format(template=template),
- value=mso.sent,
- )]
+ ops.append(dict(op='add', path=eepgs_path + '/-', value=mso.sent))
mso.existing = mso.proposed
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_filter_entry.py b/lib/ansible/modules/network/aci/mso_schema_template_filter_entry.py
index 07afbcb4b7..a3947aed23 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_filter_entry.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_filter_entry.py
@@ -30,10 +30,12 @@ options:
description:
- The name of the template.
type: list
+ required: yes
filter:
description:
- The name of the filter to manage.
type: str
+ required: yes
filter_display_name:
description:
- The name as displayed on the MSO web interface.
@@ -106,6 +108,10 @@ options:
type: str
choices: [ absent, present, query ]
default: present
+seealso:
+- module: mso_schema_template_contract_filter
+notes:
+- Due to restrictions of the MSO REST API this module creates filters when needed, and removes them when the last entry has been removed.
extends_documentation_fragment: mso
'''
@@ -168,9 +174,9 @@ def main():
argument_spec.update(
schema=dict(type='str', required=True),
template=dict(type='str', required=True),
- filter=dict(type='str', required=True), # This parameter is not required for querying all objects
+ filter=dict(type='str', required=True),
filter_display_name=dict(type='str', aliases=['filter_display_name']),
- entry=dict(type='str', required=True, aliases=['name']),
+ entry=dict(type='str', required=False, aliases=['name']), # This parameter is not required for querying all objects
description=dict(type='str', aliases=['entry_description']),
display_name=dict(type='str', aliases=['entry_display_name']),
ethertype=dict(type='str', choices=['arp', 'fcoe', 'ip', 'ipv4', 'ipv6', 'mac-security', 'mpls-unicast', 'trill', 'unspecified']),
@@ -216,14 +222,12 @@ def main():
mso = MSOModule(module)
- # Get schema_id
+ # Get schema
schema_obj = mso.get_obj('schemas', displayName=schema)
- if schema_obj:
- schema_id = schema_obj['id']
- else:
+ if not schema_obj:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -247,11 +251,19 @@ def main():
if state == 'query':
if entry is None:
+ if filter_idx is None:
+ mso.fail_json(msg="Filter '{filter}' not found".format(filter=filter_name))
mso.existing = schema_obj['templates'][template_idx]['filters'][filter_idx]['entries']
elif not mso.existing:
mso.fail_json(msg="Entry '{entry}' not found".format(entry=entry))
mso.exit_json()
+ filters_path = '/templates/{0}/filters'.format(template)
+ filter_path = '/templates/{0}/filters/{1}'.format(template, filter_name)
+ entries_path = '/templates/{0}/filters/{1}/entries'.format(template, filter_name)
+ entry_path = '/templates/{0}/filters/{1}/entries/{2}'.format(template, filter_name, entry)
+ ops = []
+
mso.previous = mso.existing
if state == 'absent':
mso.proposed = mso.sent = {}
@@ -265,18 +277,11 @@ def main():
elif len(entries) == 1:
# There is only one entry, remove filter
mso.existing = {}
- operations = [
- dict(op='remove', path='/templates/{template}/filters/{filter}'.format(template=template, filter=filter_name)),
- ]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operations)
+ ops.append(dict(op='remove', path=filter_path))
+
else:
mso.existing = {}
- operations = [
- dict(op='remove', path='/templates/{template}/filters/{filter}/entries/{entry}'.format(template=template, filter=filter_name, entry=entry)),
- ]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operations)
+ ops.append(dict(op='remove', path=entry_path))
elif state == 'present':
@@ -322,7 +327,6 @@ def main():
)
mso.sanitize(payload, collate=True)
- mso.existing = mso.sent
if filter_idx is None:
# Filter does not exist, so we have to create it
@@ -335,37 +339,31 @@ def main():
entries=[mso.sent],
)
- operations = [
- dict(op='add', path='/templates/{template}/filters/-'.format(template=template), value=payload),
- ]
+ ops.append(dict(op='add', path=filters_path + '/-', value=payload))
elif entry_idx is None:
# Entry does not exist, so we have to add it
- operations = [
- dict(op='add', path='/templates/{template}/filters/{filter}/entries/-'.format(template=template, filter=filter_name), value=mso.sent)
- ]
+ ops.append(dict(op='add', path=entries_path + '/-', value=mso.sent))
else:
# Entry exists, we have to update it
- alias = '/templates/{template}/filters/{filter}/entries/{entry}'.format(template=template, filter=filter_name, entry=entry)
- operations = [
- dict(op='replace', path='{alias}/name'.format(alias=alias), value=entry),
- dict(op='replace', path='{alias}/displayName'.format(alias=alias), value=display_name),
- dict(op='replace', path='{alias}/description'.format(alias=alias), value=description),
- dict(op='replace', path='{alias}/etherType'.format(alias=alias), value=ethertype),
- dict(op='replace', path='{alias}/ipProtocol'.format(alias=alias), value=ip_protocol),
- dict(op='replace', path='{alias}/tcpSessionRules'.format(alias=alias), value=tcp_session_rules),
- dict(op='replace', path='{alias}/sourceFrom'.format(alias=alias), value=source_from),
- dict(op='replace', path='{alias}/sourceTo'.format(alias=alias), value=source_to),
- dict(op='replace', path='{alias}/destinationFrom'.format(alias=alias), value=destination_from),
- dict(op='replace', path='{alias}/destinationTo'.format(alias=alias), value=destination_to),
- dict(op='replace', path='{alias}/arpFlag'.format(alias=alias), value=arp_flag),
- dict(op='replace', path='{alias}/stateful'.format(alias=alias), value=stateful),
- dict(op='replace', path='{alias}/matchOnlyFragments'.format(alias=alias), value=fragments_only),
- ]
-
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operations)
+ ops.append(dict(op='replace', path=entry_path + '/displayName', value=display_name))
+ ops.append(dict(op='replace', path=entry_path + '/description', value=description))
+ ops.append(dict(op='replace', path=entry_path + '/etherType', value=ethertype))
+ ops.append(dict(op='replace', path=entry_path + '/ipProtocol', value=ip_protocol))
+ ops.append(dict(op='replace', path=entry_path + '/tcpSessionRules', value=tcp_session_rules))
+ ops.append(dict(op='replace', path=entry_path + '/sourceFrom', value=source_from))
+ ops.append(dict(op='replace', path=entry_path + '/sourceTo', value=source_to))
+ ops.append(dict(op='replace', path=entry_path + '/destinationFrom', value=destination_from))
+ ops.append(dict(op='replace', path=entry_path + '/destinationTo', value=destination_to))
+ ops.append(dict(op='replace', path=entry_path + '/arpFlag', value=arp_flag))
+ ops.append(dict(op='replace', path=entry_path + '/stateful', value=stateful))
+ ops.append(dict(op='replace', path=entry_path + '/matchOnlyFragments', value=fragments_only))
+
+ mso.existing = mso.proposed
+
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_l3out.py b/lib/ansible/modules/network/aci/mso_schema_template_l3out.py
index 2a9917204d..ca6d422ff8 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_l3out.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_l3out.py
@@ -30,6 +30,7 @@ options:
description:
- The name of the template.
type: list
+ required: yes
l3out:
description:
- The name of the l3out to manage.
@@ -41,7 +42,7 @@ options:
type: str
vrf:
description:
- - The VRF associated to this ANP.
+ - The VRF associated to this L3out.
type: str
state:
description:
@@ -143,7 +144,7 @@ def main():
else:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -165,16 +166,15 @@ def main():
mso.fail_json(msg="L3out '{l3out}' not found".format(l3out=l3out))
mso.exit_json()
+ l3outs_path = '/templates/{0}/intersiteL3outs'.format(template)
+ l3out_path = '/templates/{0}/intersiteL3outs/{1}'.format(template, l3out)
+ ops = []
+
mso.previous = mso.existing
if state == 'absent':
if mso.existing:
mso.sent = mso.existing = {}
- operation = [dict(
- op='remove',
- path='/templates/{template}/intersiteL3outs/{l3out}'.format(template=template, l3out=l3out),
- )]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+ ops.append(dict(op='remove', path=l3out_path))
elif state == 'present':
vrf_ref = mso.make_reference(vrf, 'vrf', schema_id, template)
@@ -191,22 +191,14 @@ def main():
mso.sanitize(payload, collate=True)
if mso.existing:
- operation = [dict(
- op='replace',
- path='/templates/{template}/intersiteL3outs/{l3out}'.format(template=template, l3out=l3out),
- value=mso.sent,
- )]
-
+ ops.append(dict(op='replace', path=l3out_path, value=mso.sent))
else:
- operation = [dict(
- op='add',
- path='/templates/{template}/intersiteL3outs/-'.format(template=template),
- value=mso.sent,
- )]
+ ops.append(dict(op='add', path=l3outs_path + '/-', value=mso.sent))
mso.existing = mso.proposed
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()
diff --git a/lib/ansible/modules/network/aci/mso_schema_template_vrf.py b/lib/ansible/modules/network/aci/mso_schema_template_vrf.py
index e571b3ad2a..bd5e677201 100644
--- a/lib/ansible/modules/network/aci/mso_schema_template_vrf.py
+++ b/lib/ansible/modules/network/aci/mso_schema_template_vrf.py
@@ -30,6 +30,7 @@ options:
description:
- The name of the template.
type: list
+ required: yes
vrf:
description:
- The name of the VRF to manage.
@@ -138,12 +139,10 @@ def main():
# Get schema_id
schema_obj = mso.get_obj('schemas', displayName=schema)
- if schema_obj:
- schema_id = schema_obj['id']
- else:
+ if not schema_obj:
mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
- path = 'schemas/{id}'.format(id=schema_id)
+ schema_path = 'schemas/{id}'.format(**schema_obj)
# Get template
templates = [t['name'] for t in schema_obj['templates']]
@@ -165,16 +164,15 @@ def main():
mso.fail_json(msg="VRF '{vrf}' not found".format(vrf=vrf))
mso.exit_json()
+ vrfs_path = '/templates/{0}/vrfs'.format(template)
+ vrf_path = '/templates/{0}/vrfs/{1}'.format(template, vrf)
+ ops = []
+
mso.previous = mso.existing
if state == 'absent':
if mso.existing:
mso.sent = mso.existing = {}
- operation = [dict(
- op='remove',
- path='/templates/{template}/vrfs/{vrf}'.format(template=template, vrf=vrf),
- )]
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+ ops.append(dict(op='remove', path=vrf_path))
elif state == 'present':
if display_name is None and not mso.existing:
@@ -191,22 +189,14 @@ def main():
mso.sanitize(payload, collate=True)
if mso.existing:
- operation = [dict(
- op='replace',
- path='/templates/{template}/vrfs/{vrf}'.format(template=template, vrf=vrf),
- value=mso.sent,
- )]
-
+ ops.append(dict(op='replace', path=vrf_path, value=mso.sent))
else:
- operation = [dict(
- op='add',
- path='/templates/{template}/vrfs/-'.format(template=template),
- value=mso.sent,
- )]
+ ops.append(dict(op='add', path=vrfs_path + '/-', value=mso.sent))
mso.existing = mso.proposed
- if not module.check_mode:
- mso.request(path, method='PATCH', data=operation)
+
+ if not module.check_mode:
+ mso.request(schema_path, method='PATCH', data=ops)
mso.exit_json()