1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5
6from __future__ import absolute_import, division, print_function
7__metaclass__ = type
8
9ANSIBLE_METADATA = {'metadata_version': '1.1',
10                    'status': ['preview'],
11                    'supported_by': 'certified'}
12
13DOCUMENTATION = r'''
14---
15module: aci_ap
16short_description: Manage top level Application Profile (AP) objects (fv:Ap)
17description:
18- Manage top level Application Profile (AP) objects on Cisco ACI fabrics
19version_added: '2.4'
20options:
21  tenant:
22    description:
23    - The name of an existing tenant.
24    type: str
25    required: yes
26    aliases: [ tenant_name ]
27  ap:
28    description:
29    - The name of the application network profile.
30    type: str
31    required: yes
32    aliases: [ app_profile, app_profile_name, name ]
33  description:
34    description:
35    - Description for the AP.
36    type: str
37    aliases: [ descr ]
38  state:
39    description:
40    - Use C(present) or C(absent) for adding or removing.
41    - Use C(query) for listing an object or multiple objects.
42    type: str
43    choices: [ absent, present, query ]
44    default: present
45extends_documentation_fragment: aci
46notes:
47- This module does not manage EPGs, see M(aci_epg) to do this.
48- The used C(tenant) must exist before using this module in your playbook.
49  The M(aci_tenant) module can be used for this.
50seealso:
51- module: aci_tenant
52- name: APIC Management Information Model reference
53  description: More information about the internal APIC class B(fv:Ap).
54  link: https://developer.cisco.com/docs/apic-mim-ref/
55author:
56- Swetha Chunduri (@schunduri)
57'''
58
59EXAMPLES = r'''
60- name: Add a new AP
61  aci_ap:
62    host: apic
63    username: admin
64    password: SomeSecretPassword
65    tenant: production
66    ap: default
67    description: default ap
68    state: present
69  delegate_to: localhost
70
71- name: Remove an AP
72  aci_ap:
73    host: apic
74    username: admin
75    password: SomeSecretPassword
76    tenant: production
77    ap: default
78    state: absent
79  delegate_to: localhost
80
81- name: Query an AP
82  aci_ap:
83    host: apic
84    username: admin
85    password: SomeSecretPassword
86    tenant: production
87    ap: default
88    state: query
89  delegate_to: localhost
90  register: query_result
91
92- name: Query all APs
93  aci_ap:
94    host: apic
95    username: admin
96    password: SomeSecretPassword
97    state: query
98  delegate_to: localhost
99  register: query_result
100'''
101
102RETURN = r'''
103current:
104  description: The existing configuration from the APIC after the module has finished
105  returned: success
106  type: list
107  sample:
108    [
109        {
110            "fvTenant": {
111                "attributes": {
112                    "descr": "Production environment",
113                    "dn": "uni/tn-production",
114                    "name": "production",
115                    "nameAlias": "",
116                    "ownerKey": "",
117                    "ownerTag": ""
118                }
119            }
120        }
121    ]
122error:
123  description: The error information as returned from the APIC
124  returned: failure
125  type: dict
126  sample:
127    {
128        "code": "122",
129        "text": "unknown managed object class foo"
130    }
131raw:
132  description: The raw output returned by the APIC REST API (xml or json)
133  returned: parse error
134  type: str
135  sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
136sent:
137  description: The actual/minimal configuration pushed to the APIC
138  returned: info
139  type: list
140  sample:
141    {
142        "fvTenant": {
143            "attributes": {
144                "descr": "Production environment"
145            }
146        }
147    }
148previous:
149  description: The original configuration from the APIC before the module has started
150  returned: info
151  type: list
152  sample:
153    [
154        {
155            "fvTenant": {
156                "attributes": {
157                    "descr": "Production",
158                    "dn": "uni/tn-production",
159                    "name": "production",
160                    "nameAlias": "",
161                    "ownerKey": "",
162                    "ownerTag": ""
163                }
164            }
165        }
166    ]
167proposed:
168  description: The assembled configuration from the user-provided parameters
169  returned: info
170  type: dict
171  sample:
172    {
173        "fvTenant": {
174            "attributes": {
175                "descr": "Production environment",
176                "name": "production"
177            }
178        }
179    }
180filter_string:
181  description: The filter string used for the request
182  returned: failure or debug
183  type: str
184  sample: ?rsp-prop-include=config-only
185method:
186  description: The HTTP method used for the request to the APIC
187  returned: failure or debug
188  type: str
189  sample: POST
190response:
191  description: The HTTP response from the APIC
192  returned: failure or debug
193  type: str
194  sample: OK (30 bytes)
195status:
196  description: The HTTP status from the APIC
197  returned: failure or debug
198  type: int
199  sample: 200
200url:
201  description: The HTTP url used for the request to the APIC
202  returned: failure or debug
203  type: str
204  sample: https://10.11.12.13/api/mo/uni/tn-production.json
205'''
206
207from ansible.module_utils.basic import AnsibleModule
208from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
209
210
211def main():
212    argument_spec = aci_argument_spec()
213    argument_spec.update(
214        tenant=dict(type='str', aliases=['tenant_name']),  # Not required for querying all objects
215        ap=dict(type='str', aliases=['app_profile', 'app_profile_name', 'name']),  # Not required for querying all objects
216        description=dict(type='str', aliases=['descr']),
217        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
218    )
219
220    module = AnsibleModule(
221        argument_spec=argument_spec,
222        supports_check_mode=True,
223        required_if=[
224            ['state', 'absent', ['tenant', 'ap']],
225            ['state', 'present', ['tenant', 'ap']],
226        ],
227    )
228
229    ap = module.params['ap']
230    description = module.params['description']
231    state = module.params['state']
232    tenant = module.params['tenant']
233
234    aci = ACIModule(module)
235    aci.construct_url(
236        root_class=dict(
237            aci_class='fvTenant',
238            aci_rn='tn-{0}'.format(tenant),
239            module_object=tenant,
240            target_filter={'name': tenant},
241        ),
242        subclass_1=dict(
243            aci_class='fvAp',
244            aci_rn='ap-{0}'.format(ap),
245            module_object=ap,
246            target_filter={'name': ap},
247        ),
248    )
249
250    aci.get_existing()
251
252    if state == 'present':
253        aci.payload(
254            aci_class='fvAp',
255            class_config=dict(
256                name=ap,
257                descr=description,
258            ),
259        )
260
261        aci.get_diff(aci_class='fvAp')
262
263        aci.post_config()
264
265    elif state == 'absent':
266        aci.delete_config()
267
268    aci.exit_json()
269
270
271if __name__ == "__main__":
272    main()
273