1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# Copyright: (c) 2019, Dag Wieers (@dagwieers) <dag@wieers.com>
5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
6
7from __future__ import absolute_import, division, print_function
8__metaclass__ = type
9
10ANSIBLE_METADATA = {'metadata_version': '1.1',
11                    'status': ['preview'],
12                    'supported_by': 'community'}
13
14DOCUMENTATION = r'''
15---
16module: mso_schema_site_vrf_region
17short_description: Manage site-local VRF regions in schema template
18description:
19- Manage site-local VRF regions in schema template on Cisco ACI Multi-Site.
20author:
21- Dag Wieers (@dagwieers)
22version_added: '2.8'
23options:
24  schema:
25    description:
26    - The name of the schema.
27    type: str
28    required: yes
29  site:
30    description:
31    - The name of the site.
32    type: str
33    required: yes
34  template:
35    description:
36    - The name of the template.
37    type: str
38    required: yes
39  vrf:
40    description:
41    - The name of the VRF.
42    type: str
43  region:
44    description:
45    - The name of the region to manage.
46    type: str
47    aliases: [ name ]
48  state:
49    description:
50    - Use C(present) or C(absent) for adding or removing.
51    - Use C(query) for listing an object or multiple objects.
52    type: str
53    choices: [ absent, present, query ]
54    default: present
55seealso:
56- module: mso_schema_site_vrf
57- module: mso_schema_template_vrf
58extends_documentation_fragment: mso
59'''
60
61EXAMPLES = r'''
62- name: Add a new site VRF region
63  mso_schema_template_vrf_region:
64    host: mso_host
65    username: admin
66    password: SomeSecretPassword
67    schema: Schema1
68    site: Site1
69    template: Template1
70    vrf: VRF1
71    region: us-west-1
72    state: present
73  delegate_to: localhost
74
75- name: Remove a site VRF region
76  mso_schema_template_vrf_region:
77    host: mso_host
78    username: admin
79    password: SomeSecretPassword
80    schema: Schema1
81    site: Site1
82    template: Template1
83    vrf: VRF1
84    region: us-west-1
85    state: absent
86  delegate_to: localhost
87
88- name: Query a specific site VRF region
89  mso_schema_template_vrf_region:
90    host: mso_host
91    username: admin
92    password: SomeSecretPassword
93    schema: Schema1
94    site: Site1
95    template: Template1
96    vrf: VRF1
97    region: us-west-1
98    state: query
99  delegate_to: localhost
100  register: query_result
101
102- name: Query all site VRF regions
103  mso_schema_template_vrf_region:
104    host: mso_host
105    username: admin
106    password: SomeSecretPassword
107    schema: Schema1
108    site: Site1
109    template: Template1
110    vrf: VRF1
111    state: query
112  delegate_to: localhost
113  register: query_result
114'''
115
116RETURN = r'''
117'''
118
119from ansible.module_utils.basic import AnsibleModule
120from ansible.module_utils.network.aci.mso import MSOModule, mso_argument_spec
121
122
123def main():
124    argument_spec = mso_argument_spec()
125    argument_spec.update(
126        schema=dict(type='str', required=True),
127        site=dict(type='str', required=True),
128        template=dict(type='str', required=True),
129        vrf=dict(type='str', required=True),
130        region=dict(type='str', aliases=['name']),  # This parameter is not required for querying all objects
131        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
132    )
133
134    module = AnsibleModule(
135        argument_spec=argument_spec,
136        supports_check_mode=True,
137        required_if=[
138            ['state', 'absent', ['region']],
139            ['state', 'present', ['region']],
140        ],
141    )
142
143    schema = module.params['schema']
144    site = module.params['site']
145    template = module.params['template']
146    vrf = module.params['vrf']
147    region = module.params['region']
148    state = module.params['state']
149
150    mso = MSOModule(module)
151
152    # Get schema_id
153    schema_obj = mso.get_obj('schemas', displayName=schema)
154    if not schema_obj:
155        mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
156
157    schema_path = 'schemas/{id}'.format(**schema_obj)
158    schema_id = schema_obj['id']
159
160    # Get site
161    site_id = mso.lookup_site(site)
162
163    # Get site_idx
164    sites = [(s['siteId'], s['templateName']) for s in schema_obj['sites']]
165    if (site_id, template) not in sites:
166        mso.fail_json(msg="Provided site/template '{0}-{1}' does not exist. Existing sites/templates: {2}".format(site, template, ', '.join(sites)))
167
168    # Schema-access uses indexes
169    site_idx = sites.index((site_id, template))
170    # Path-based access uses site_id-template
171    site_template = '{0}-{1}'.format(site_id, template)
172
173    # Get VRF
174    vrf_ref = mso.vrf_ref(schema_id=schema_id, template=template, vrf=vrf)
175    vrfs = [v['vrfRef'] for v in schema_obj['sites'][site_idx]['vrfs']]
176    if vrf_ref not in vrfs:
177        mso.fail_json(msg="Provided vrf '{0}' does not exist. Existing vrfs: {1}".format(vrf, ', '.join(vrfs)))
178    vrf_idx = vrfs.index(vrf_ref)
179
180    # Get Region
181    regions = [r['name'] for r in schema_obj['sites'][site_idx]['vrfs'][vrf_idx]['regions']]
182    if region is not None and region in regions:
183        region_idx = regions.index(region)
184        region_path = '/sites/{0}/vrfs/{1}/regions/{2}'.format(site_template, vrf, region)
185        mso.existing = schema_obj['sites'][site_idx]['vrfs'][vrf_idx]['regions'][region_idx]
186
187    if state == 'query':
188        if region is None:
189            mso.existing = schema_obj['sites'][site_idx]['vrfs'][vrf_idx]['regions']
190        elif not mso.existing:
191            mso.fail_json(msg="Region '{region}' not found".format(region=region))
192        mso.exit_json()
193
194    regions_path = '/sites/{0}/vrfs/{1}/regions'.format(site_template, vrf)
195    ops = []
196
197    mso.previous = mso.existing
198    if state == 'absent':
199        if mso.existing:
200            mso.sent = mso.existing = {}
201            ops.append(dict(op='remove', path=region_path))
202
203    elif state == 'present':
204
205        payload = dict(
206            name=region,
207        )
208
209        mso.sanitize(payload, collate=True)
210
211        if mso.existing:
212            ops.append(dict(op='replace', path=region_path, value=mso.sent))
213        else:
214            ops.append(dict(op='add', path=regions_path + '/-', value=mso.sent))
215
216        mso.existing = mso.proposed
217
218    if not module.check_mode:
219        mso.request(schema_path, method='PATCH', data=ops)
220
221    mso.exit_json()
222
223
224if __name__ == "__main__":
225    main()
226