aci_rest: Accept YAML input and validate content input
This PR includes: - Accept inline YAML, YAML string, inline JSON, JSON string input and XML string input - Validate YAML, JSON and XML input
This commit is contained in:
parent
a796391c9b
commit
a200ecf966
1 changed files with 64 additions and 4 deletions
|
@ -70,7 +70,22 @@ EXAMPLES = r'''
|
|||
src: /home/cisco/ansible/aci/configs/aci_config.xml
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Add a tenant
|
||||
- name: Add a tenant using inline YAML
|
||||
aci_rest:
|
||||
hostname: '{{ inventory_hostname }}'
|
||||
username: '{{ aci_username }}'
|
||||
password: '{{ aci_password }}'
|
||||
validate_certs: no
|
||||
path: /api/mo/uni/tn-[Sales].json
|
||||
method: post
|
||||
content:
|
||||
fvTenant:
|
||||
attributes:
|
||||
name: Sales
|
||||
descr: Sales departement
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Add a tenant using a JSON string
|
||||
aci_rest:
|
||||
hostname: '{{ inventory_hostname }}'
|
||||
username: '{{ aci_username }}'
|
||||
|
@ -89,6 +104,18 @@ EXAMPLES = r'''
|
|||
}
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Add a tenant using an XML string
|
||||
aci_rest:
|
||||
hostname: '{{ inventory_hostname }}'
|
||||
username: '{{ aci_username }}'
|
||||
password: '{{ aci_password }}'
|
||||
validate_certs: no
|
||||
path: /api/mo/uni/tn-[Sales].xml
|
||||
method: post
|
||||
content: |
|
||||
<fvTenant name="Sales" descr="Sales departement"/>
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Get tenants
|
||||
aci_rest:
|
||||
hostname: '{{ inventory_hostname }}'
|
||||
|
@ -187,6 +214,7 @@ url:
|
|||
sample: https://1.2.3.4/api/mo/uni/tn-[Dag].json?rsp-subtree=modified
|
||||
'''
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
try:
|
||||
|
@ -211,9 +239,17 @@ try:
|
|||
except ImportError:
|
||||
HAS_XMLJSON_COBRA = False
|
||||
|
||||
# Optional, only used for YAML validation
|
||||
try:
|
||||
import yaml
|
||||
HAS_YAML = True
|
||||
except:
|
||||
HAS_YAML = False
|
||||
|
||||
from ansible.module_utils.aci import ACIModule, aci_argument_spec, aci_response_json, aci_response_xml
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.urls import fetch_url
|
||||
from ansible.module_utils._text import to_text
|
||||
|
||||
|
||||
def update_qsl(url, params):
|
||||
|
@ -267,7 +303,7 @@ def main():
|
|||
path=dict(type='str', required=True, aliases=['uri']),
|
||||
method=dict(type='str', default='get', choices=['delete', 'get', 'post'], aliases=['action']),
|
||||
src=dict(type='path', aliases=['config_file']),
|
||||
content=dict(type='str'),
|
||||
content=dict(type='raw'),
|
||||
)
|
||||
|
||||
module = AnsibleModule(
|
||||
|
@ -311,6 +347,30 @@ def main():
|
|||
# TODO: Would be nice to template this, requires action-plugin
|
||||
payload = config_object.read()
|
||||
|
||||
# Validate content
|
||||
if rest_type == 'json':
|
||||
if content and isinstance(content, dict):
|
||||
# Validate inline YAML/JSON
|
||||
payload = json.dumps(payload)
|
||||
elif payload and isinstance(payload, str) and HAS_YAML:
|
||||
try:
|
||||
# Validate YAML/JSON string
|
||||
payload = json.dumps(yaml.load(payload))
|
||||
except Exception as e:
|
||||
module.fail_json(msg='Failed to parse provided JSON/YAML content: %s' % to_text(e), exception=to_text(e), payload=payload)
|
||||
elif rest_type == 'xml' and HAS_LXML_ETREE:
|
||||
if content and isinstance(content, dict) and HAS_XMLJSON_COBRA:
|
||||
# Validate inline YAML/JSON
|
||||
# FIXME: Converting from a dictionary to XML is unsupported at this time
|
||||
# payload = etree.tostring(payload)
|
||||
pass
|
||||
elif payload and isinstance(payload, str):
|
||||
try:
|
||||
# Validate XML string
|
||||
payload = lxml.etree.tostring(lxml.etree.fromstring(payload))
|
||||
except Exception as e:
|
||||
module.fail_json(msg='Failed to parse provided XML content: %s' % to_text(e), payload=payload)
|
||||
|
||||
# Perform actual request using auth cookie (Same as aci_request,but also supports XML)
|
||||
url = '%(protocol)s://%(hostname)s/' % aci.params + path.lstrip('/')
|
||||
if method != 'get':
|
||||
|
@ -325,9 +385,9 @@ def main():
|
|||
if info['status'] != 200:
|
||||
try:
|
||||
aci_response(aci.result, info['body'], rest_type)
|
||||
module.fail_json(msg='Request failed: %(error_code)s %(error_text)s' % aci.result, **aci.result)
|
||||
module.fail_json(msg='Request failed: %(error_code)s %(error_text)s' % aci.result, payload=payload, **aci.result)
|
||||
except KeyError:
|
||||
module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info, **aci.result)
|
||||
module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info, payload=payload, **aci.result)
|
||||
|
||||
aci_response(aci.result, resp.read(), rest_type)
|
||||
|
||||
|
|
Loading…
Reference in a new issue