Add to_xml and from_xml filter plugin (#56)

Add to_xml and from_xml filter plugin

Reviewed-by: https://github.com/apps/ansible-zuul
pull/67/head
Ashwini Mhatre 2021-04-09 18:50:17 +05:30 committed by GitHub
parent c04eecdfc2
commit 43e77543d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 931 additions and 0 deletions

View File

@ -21,9 +21,11 @@ PEP440 is the schema used to describe the versions of Ansible.
### Filter plugins ### Filter plugins
Name | Description Name | Description
--- | --- --- | ---
[ansible.utils.from_xml](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.from_xml_filter.rst)|Convert given XML string to native python dictionary.
[ansible.utils.get_path](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.get_path_filter.rst)|Retrieve the value in a variable using a path [ansible.utils.get_path](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.get_path_filter.rst)|Retrieve the value in a variable using a path
[ansible.utils.index_of](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.index_of_filter.rst)|Find the indices of items in a list matching some criteria [ansible.utils.index_of](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.index_of_filter.rst)|Find the indices of items in a list matching some criteria
[ansible.utils.to_paths](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.to_paths_filter.rst)|Flatten a complex object into a dictionary of paths and values [ansible.utils.to_paths](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.to_paths_filter.rst)|Flatten a complex object into a dictionary of paths and values
[ansible.utils.to_xml](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.to_xml_filter.rst)|Convert given JSON string to XML
[ansible.utils.validate](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.validate_filter.rst)|Validate data with provided criteria [ansible.utils.validate](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.validate_filter.rst)|Validate data with provided criteria
### Lookup plugins ### Lookup plugins

View File

@ -0,0 +1,3 @@
---
minor_changes:
- Add from_xml and to_xml fiter plugin (https://github.com/ansible-collections/ansible.utils/pull/56).

View File

@ -0,0 +1,173 @@
.. _ansible.utils.from_xml_filter:
**********************
ansible.utils.from_xml
**********************
**Convert given XML string to native python dictionary.**
Version added: 2.0.2
.. contents::
:local:
:depth: 1
Synopsis
--------
- This plugin converts the XML string to a native python dictionary.
- Using the parameters below- ``data|ansible.utils.from_xml``
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>data</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>The input XML string.</div>
<div>This option represents the XML value that is passed to the filter plugin in pipe format.</div>
<div>For example <code>config_data|ansible.utils.from_xml</code>, in this case <code>config_data</code> represents this option.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>engine</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"xmltodict"</div>
</td>
<td>
</td>
<td>
<div>Conversion library to use within the filter plugin.</div>
</td>
</tr>
</table>
<br/>
Examples
--------
.. code-block:: yaml
#### Simple examples with out any engine. plugin will use default value as xmltodict
tasks:
- name: convert given XML to native python dictionary
ansible.builtin.set_fact:
data: "
<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema/></schemas></netconf-state>
"
- debug:
msg: "{{ data|ansible.utils.from_xml }}"
##TASK######
# TASK [convert given XML to native python dictionary] *****************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:5
# ok: [localhost] => {
# "ansible_facts": {
# "data": " <netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema/></schemas></netconf-state> "
# },
# "changed": false
# }
#
# TASK [debug] *************************************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:13
# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": {
# "netconf-state": {
# "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
# "schemas": {
# "schema": null
# }
# }
# }
# }
#### example2 with engine=xmltodict
tasks:
- name: convert given XML to native python dictionary
ansible.builtin.set_fact:
data: "
<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema/></schemas></netconf-state>
"
- debug:
msg: "{{ data|ansible.utils.from_xml('xmltodict') }}"
##TASK######
# TASK [convert given XML to native python dictionary] *****************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:5
# ok: [localhost] => {
# "ansible_facts": {
# "data": " <netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema/></schemas></netconf-state> "
# },
# "changed": false
# }
#
# TASK [debug] *************************************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:13
# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": {
# "netconf-state": {
# "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
# "schemas": {
# "schema": null
# }
# }
# }
# }
Status
------
Authors
~~~~~~~
- Ashwini Mhatre (@amhatre)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@ -0,0 +1,166 @@
.. _ansible.utils.to_xml_filter:
********************
ansible.utils.to_xml
********************
**Convert given JSON string to XML**
Version added: 2.0.2
.. contents::
:local:
:depth: 1
Synopsis
--------
- This plugin converts the JSON string to XML.
- Using the parameters below- ``data|ansible.utils.to_xml``
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>data</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>The input JSON string .</div>
<div>This option represents the JSON value that is passed to the filter plugin in pipe format.</div>
<div>For example <code>config_data|ansible.utils.to_xml</code>, in this case <code>config_data</code> represents this option.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>engine</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"xmltodict"</div>
</td>
<td>
</td>
<td>
<div>Conversion library to use within the filter plugin.</div>
</td>
</tr>
</table>
<br/>
Examples
--------
.. code-block:: yaml
#### Simple examples with out any engine. plugin will use default value as xmltodict
- name: Define JSON data
ansible.builtin.set_fact:
data:
"interface-configurations":
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
"interface-configuration":
- debug:
msg: "{{ data|ansible.utils.to_xml }}"
# TASK [Define JSON data ] *************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:5
# ok: [localhost] => {
# "ansible_facts": {
# "data": {
# "interface-configurations": {
# "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
# "interface-configuration": null
# }
# }
# },
# "changed": false
# }
#
# TASK [debug] ***********************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:13
# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<interface-configurations xmlns=\"http://cisco.com/ns/yang/
# Cisco-IOS-XR-ifmgr-cfg\">\n\t<interface-configuration></interface-configuration>\n</interface-configurations>"
# }
#### example2 with engine=xmltodict
- name: Define JSON data
ansible.builtin.set_fact:
data:
"interface-configurations":
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
"interface-configuration":
- debug:
msg: "{{ data|ansible.utils.to_xml('xmltodict') }}"
# TASK [Define JSON data ] *************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:5
# ok: [localhost] => {
# "ansible_facts": {
# "data": {
# "interface-configurations": {
# "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
# "interface-configuration": null
# }
# }
# },
# "changed": false
# }
# TASK [debug] ***********************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:13
# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<interface-configurations xmlns=\"http://cisco.com/ns/yang/
# Cisco-IOS-XR-ifmgr-cfg\">\n\t<interface-configuration></interface-configuration>\n</interface-configurations>"
# }
Status
------
Authors
~~~~~~~
- Ashwini Mhatre (@amhatre)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

145
plugins/filter/from_xml.py Normal file
View File

@ -0,0 +1,145 @@
#
# -*- coding: utf-8 -*-
# Copyright 2021 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The from_xml filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: from_xml
author: Ashwini Mhatre (@amhatre)
version_added: "2.0.2"
short_description: Convert given XML string to native python dictionary.
description:
- This plugin converts the XML string to a native python dictionary.
- Using the parameters below- C(data|ansible.utils.from_xml)
options:
data:
description:
- The input XML string.
- This option represents the XML value that is passed to the filter plugin in pipe format.
- For example C(config_data|ansible.utils.from_xml), in this case C(config_data) represents this option.
type: str
required: True
engine:
description:
- Conversion library to use within the filter plugin.
type: str
default: xmltodict
"""
EXAMPLES = r"""
#### Simple examples with out any engine. plugin will use default value as xmltodict
tasks:
- name: convert given XML to native python dictionary
ansible.builtin.set_fact:
data: "
<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema/></schemas></netconf-state>
"
- debug:
msg: "{{ data|ansible.utils.from_xml }}"
##TASK######
# TASK [convert given XML to native python dictionary] *****************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:5
# ok: [localhost] => {
# "ansible_facts": {
# "data": " <netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema/></schemas></netconf-state> "
# },
# "changed": false
# }
#
# TASK [debug] *************************************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:13
# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": {
# "netconf-state": {
# "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
# "schemas": {
# "schema": null
# }
# }
# }
# }
#### example2 with engine=xmltodict
tasks:
- name: convert given XML to native python dictionary
ansible.builtin.set_fact:
data: "
<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema/></schemas></netconf-state>
"
- debug:
msg: "{{ data|ansible.utils.from_xml('xmltodict') }}"
##TASK######
# TASK [convert given XML to native python dictionary] *****************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:5
# ok: [localhost] => {
# "ansible_facts": {
# "data": " <netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema/></schemas></netconf-state> "
# },
# "changed": false
# }
#
# TASK [debug] *************************************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils.yaml:13
# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": {
# "netconf-state": {
# "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
# "schemas": {
# "schema": null
# }
# }
# }
# }
"""
from ansible.errors import AnsibleFilterError
from jinja2.filters import environmentfilter
from ansible_collections.ansible.utils.plugins.plugin_utils.from_xml import (
from_xml,
)
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
@environmentfilter
def _from_xml(*args, **kwargs):
"""Convert the given data from xml to json."""
keys = ["data", "engine"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(
data=data, schema=DOCUMENTATION, name="from_xml"
)
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return from_xml(**updated_data)
class FilterModule(object):
""" from_xml """
def filters(self):
"""a mapping of filter names to functions"""
return {"from_xml": _from_xml}

138
plugins/filter/to_xml.py Normal file
View File

@ -0,0 +1,138 @@
#
# -*- coding: utf-8 -*-
# Copyright 2021 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The to_xml filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: to_xml
author: Ashwini Mhatre (@amhatre)
version_added: "2.0.2"
short_description: Convert given JSON string to XML
description:
- This plugin converts the JSON string to XML.
- Using the parameters below- C(data|ansible.utils.to_xml)
options:
data:
description:
- The input JSON string .
- This option represents the JSON value that is passed to the filter plugin in pipe format.
- For example C(config_data|ansible.utils.to_xml), in this case C(config_data) represents this option.
type: dict
required: True
engine:
description:
- Conversion library to use within the filter plugin.
type: str
default: xmltodict
"""
EXAMPLES = r"""
#### Simple examples with out any engine. plugin will use default value as xmltodict
- name: Define JSON data
ansible.builtin.set_fact:
data:
"interface-configurations":
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
"interface-configuration":
- debug:
msg: "{{ data|ansible.utils.to_xml }}"
# TASK [Define JSON data ] *************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:5
# ok: [localhost] => {
# "ansible_facts": {
# "data": {
# "interface-configurations": {
# "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
# "interface-configuration": null
# }
# }
# },
# "changed": false
# }
#
# TASK [debug] ***********************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:13
# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<interface-configurations xmlns=\"http://cisco.com/ns/yang/
# Cisco-IOS-XR-ifmgr-cfg\">\n\t<interface-configuration></interface-configuration>\n</interface-configurations>"
# }
#### example2 with engine=xmltodict
- name: Define JSON data
ansible.builtin.set_fact:
data:
"interface-configurations":
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
"interface-configuration":
- debug:
msg: "{{ data|ansible.utils.to_xml('xmltodict') }}"
# TASK [Define JSON data ] *************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:5
# ok: [localhost] => {
# "ansible_facts": {
# "data": {
# "interface-configurations": {
# "@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
# "interface-configuration": null
# }
# }
# },
# "changed": false
# }
# TASK [debug] ***********************************************************************************************************
# task path: /Users/amhatre/ansible-collections/playbooks/test_utils_json_to_xml.yaml:13
# Loading collection ansible.utils from /Users/amhatre/ansible-collections/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<interface-configurations xmlns=\"http://cisco.com/ns/yang/
# Cisco-IOS-XR-ifmgr-cfg\">\n\t<interface-configuration></interface-configuration>\n</interface-configurations>"
# }
"""
from ansible.errors import AnsibleFilterError
from jinja2.filters import environmentfilter
from ansible_collections.ansible.utils.plugins.plugin_utils.to_xml import (
to_xml,
)
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
@environmentfilter
def _to_xml(*args, **kwargs):
"""Convert the given data from json to xml."""
keys = ["data", "engine"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(
data=data, schema=DOCUMENTATION, name="to_xml"
)
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return to_xml(**updated_data)
class FilterModule(object):
""" to_xml """
def filters(self):
"""a mapping of filter names to functions"""
return {"to_xml": _to_xml}

View File

@ -0,0 +1,52 @@
#
# -*- coding: utf-8 -*-
# Copyright 2021 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The from_xml plugin code
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
from ansible.errors import AnsibleFilterError
try:
import xmltodict
HAS_XMLTODICT = True
except ImportError:
HAS_XMLTODICT = False
def _raise_error(msg):
"""Raise an error message, prepend with filter name
:param msg: The message
:type msg: str
:raises: AnsibleError
"""
error = "Error when using plugin 'from_xml': {msg}".format(msg=msg)
raise AnsibleFilterError(error)
def from_xml(data, engine):
"""Convert data which is in xml to json"
:param data: The data passed in (data|from_xml(...))
:type data: xml
:param engine: Conversion library default=xml_to_dict
"""
if engine == "xmltodict":
if not HAS_XMLTODICT:
_raise_error("Missing required library xmltodict")
try:
res = json.dumps(xmltodict.parse(data))
except Exception:
_raise_error("Input Xml is not valid")
return res
else:
error = "engine: {engine} is not supported ".format(engine=engine)
_raise_error(error)

View File

@ -0,0 +1,53 @@
#
# -*- coding: utf-8 -*-
# Copyright 2021 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The to_xml plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.errors import AnsibleFilterError
try:
import xmltodict
HAS_XMLTODICT = True
except ImportError:
HAS_XMLTODICT = False
def _raise_error(msg):
"""Raise an error message, prepend with filter name
:param msg: The message
:type msg: str
:raises: AnsibleError
"""
error = "Error when using plugin 'to_xml': {msg}".format(msg=msg)
raise AnsibleFilterError(error)
def to_xml(data, engine):
"""Convert data which is in json to xml"
:param data: The data passed in (data|to_xml(...))
:type data: xml
:param engine: Conversion library default=xmltodict
"""
if engine == "xmltodict":
if not HAS_XMLTODICT:
_raise_error("Missing required library xmltodict")
try:
res = xmltodict.unparse(data, pretty=True)
except Exception:
_raise_error("Input json is not valid")
return res
else:
error = "engine: {engine} is not supported ".format(engine=engine)
_raise_error(error)

View File

@ -0,0 +1,39 @@
---
- name: Setup xml and expected json
ansible.builtin.set_fact:
data: "
<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema/></schemas></netconf-state>
"
output: {
"netconf-state": {
"@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring",
"schemas": {
"schema": null
}
}
}
- debug:
msg: "{{ data|ansible.utils.from_xml() }}"
- name: Integration tests with and without default engine as xmltodict and
assert:
that: "{{ output == item.test }}"
loop:
- test: "{{ data|ansible.utils.from_xml() }}"
- test: "{{ data|ansible.utils.from_xml('xmltodict') }}"
- name: Setup invalid xml as input to ansible.utils.from_xml.
ansible.builtin.set_fact:
data: "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">"
- name: validate input xml
ansible.builtin.set_fact:
_result: "{{ data|ansible.utils.from_xml() }}"
ignore_errors: true
register: result
- assert:
that: "{{ msg in result.msg }}"
vars:
msg: "Error when using plugin 'from_xml': Input Xml is not valid"

View File

@ -0,0 +1,13 @@
---
- name: Recursively find all test files
find:
file_type: file
paths: "{{ role_path }}/tasks/include"
recurse: true
use_regex: true
patterns:
- '^(?!_).+$'
register: found
- include: "{{ item.path }}"
loop: "{{ found.files }}"

View File

@ -0,0 +1,35 @@
---
- name: Setup xml and expected json
ansible.builtin.set_fact:
data:
"interface-configurations":
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
"interface-configuration":
output: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<interface-configurations xmlns=\"http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg\">\n\t<interface-configuration></interface-configuration>\n</interface-configurations>"
- debug:
msg: "{{ data|ansible.utils.to_xml() }}"
- name: Integration tests with and without default engine as xmltodict and
assert:
that: "{{ output == item.test }}"
loop:
- test: "{{ data|ansible.utils.to_xml() }}"
- test: "{{ data|ansible.utils.to_xml('xmltodict') }}"
- name: test for supported engine for to_xml filter
ansible.builtin.set_fact:
data:
"interface-configurations":
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
- name: validate input xml
ansible.builtin.set_fact:
_result: "{{ data|ansible.utils.to_xml('dicttoxml') }}"
ignore_errors: true
register: result
- assert:
that: "{{ msg in result.msg }}"
vars:
msg: "Error when using plugin 'to_xml': engine: dicttoxml is not supported"

View File

@ -0,0 +1,13 @@
---
- name: Recursively find all test files
find:
file_type: file
paths: "{{ role_path }}/tasks/include"
recurse: true
use_regex: true
patterns:
- '^(?!_).+$'
register: found
- include: "{{ item.path }}"
loop: "{{ found.files }}"

View File

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# Copyright 2020 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import unittest
from ansible.errors import AnsibleError
from ansible_collections.ansible.utils.plugins.filter.from_xml import from_xml
INVALID_DATA = '<netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">'
VALID_DATA = (
'<netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">'
"<schemas><schema/></schemas></netconf-state>"
)
OUTPUT = """{"netconf-state": \
{"@xmlns": "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring", "schemas": {"schema": null}}}"""
class TestFromXml(unittest.TestCase):
def setUp(self):
pass
def test_invalid_data(self):
"""Check passing invalid argspec"""
# missing required arguments
args = [INVALID_DATA, "xmltodict"]
kwargs = {}
with self.assertRaises(AnsibleError) as error:
from_xml(*args, **kwargs)
print(str(error.exception))
self.assertIn(
"Error when using plugin 'from_xml': Input Xml is not valid",
str(error.exception),
)
def test_valid_data(self):
"""Check passing valid data as per criteria"""
self.maxDiff = None
args = [VALID_DATA, "xmltodict"]
result = from_xml(*args)
print(result)
self.assertEqual(result, OUTPUT)

View File

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# Copyright 2020 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import unittest
from ansible.errors import AnsibleError
from ansible_collections.ansible.utils.plugins.filter.to_xml import to_xml
INVALID_DATA = '<netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">'
VALID_DATA = {
"interface-configurations": {
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
}
}
OUTPUT = """<?xml version="1.0" encoding="utf-8"?>
<interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"></interface-configurations>"""
class TestToXml(unittest.TestCase):
def setUp(self):
pass
def test_invalid_data(self):
"""Check passing invalid argspec"""
# missing required arguments
args = [INVALID_DATA, "xmltodict"]
kwargs = {}
with self.assertRaises(AnsibleError) as error:
to_xml(*args, **kwargs)
print(str(error.exception))
self.assertIn(
"Error when using plugin 'to_xml': Input json is not valid",
str(error.exception),
)
def test_valid_data(self):
"""Check passing valid data as per criteria"""
self.maxDiff = None
args = [VALID_DATA, "xmltodict"]
result = to_xml(*args)
print(result)
self.assertEqual(result, OUTPUT)