Recursive filter plugins remove_keys | replace_keys | keep_keys (#110)
Recursive filter plugins remove_keys | replace_keys | keep_keys SUMMARY New plugins remove_keys replace_keys keep_keys ISSUE TYPE New Module Pull Request COMPONENT NAME remove_keys replace_keys keep_keys ADDITIONAL INFORMATION Reviewed-by: Ashwini Mhatre <mashu97@gmail.com> Reviewed-by: Nilashish Chakraborty <nilashishchakraborty8@gmail.com> Reviewed-by: None <None>pull/134/head
parent
ea54e97359
commit
624bc76e26
|
@ -130,3 +130,6 @@ dmypy.json
|
||||||
|
|
||||||
# Pyre type checker
|
# Pyre type checker
|
||||||
.pyre/
|
.pyre/
|
||||||
|
|
||||||
|
# ide
|
||||||
|
.vscode
|
||||||
|
|
|
@ -26,6 +26,12 @@ Name | Description
|
||||||
[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.hwaddr](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.hwaddr_filter.rst)|HWaddr / MAC address filters
|
[ansible.utils.hwaddr](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.hwaddr_filter.rst)|HWaddr / MAC address filters
|
||||||
[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.keep_keys](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.keep_keys_filter.rst)|Keep specific keys from a data recursively.
|
||||||
|
[ansible.utils.nthhost](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.nthhost_filter.rst)|This filter returns the nth host within a network described by value.
|
||||||
|
[ansible.utils.ipv4](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipv4_filter.rst)|To filter only Ipv4 addresses Ipv4 filter is used.
|
||||||
|
[ansible.utils.param_list_compare](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.param_list_compare_filter.rst)|Generate the final param list combining/comparing base and provided parameters.
|
||||||
|
[ansible.utils.remove_keys](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.remove_keys_filter.rst)|Remove specific keys from a data recursively.
|
||||||
|
[ansible.utils.replace_keys](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.replace_keys_filter.rst)|Replaces specific keys with their after value from a data recursively.
|
||||||
[ansible.utils.macaddr](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.macaddr_filter.rst)|macaddr / MAC address filters
|
[ansible.utils.macaddr](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.macaddr_filter.rst)|macaddr / MAC address filters
|
||||||
[ansible.utils.slaac](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.slaac_filter.rst)|This filter returns the SLAAC address within a network for a given HW/MAC address.
|
[ansible.utils.slaac](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.slaac_filter.rst)|This filter returns the SLAAC address within a network for a given HW/MAC address.
|
||||||
[ansible.utils.ipaddr](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipaddr_filter.rst)|This filter is designed to return the input value if a query is True, else False.
|
[ansible.utils.ipaddr](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipaddr_filter.rst)|This filter is designed to return the input value if a query is True, else False.
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- "'keep_keys' filter plugin added."
|
||||||
|
- "'remove_keys' filter plugin added."
|
||||||
|
- "'replace_keys' filter plugin added."
|
|
@ -0,0 +1,374 @@
|
||||||
|
.. _ansible.utils.keep_keys_filter:
|
||||||
|
|
||||||
|
|
||||||
|
***********************
|
||||||
|
ansible.utils.keep_keys
|
||||||
|
***********************
|
||||||
|
|
||||||
|
**Keep specific keys from a data recursively.**
|
||||||
|
|
||||||
|
|
||||||
|
Version added: 2.5.0
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- This plugin keep only specified keys from a provided data recursively.
|
||||||
|
- Matching parameter defaults to equals unless ``matching_parameter`` is explicitly mentioned.
|
||||||
|
- Using the parameters below- ``data|ansible.utils.keep_keys(target([....]``))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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">raw</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>This option represents a list of dictionaries or a dictionary with any level of nesting data.</div>
|
||||||
|
<div>For example <code>config_data|ansible.utils.keep_keys(target([....]</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>matching_parameter</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>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>starts_with</li>
|
||||||
|
<li>ends_with</li>
|
||||||
|
<li>regex</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Specify the matching configuration of target keys and data attributes.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>target</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Specify the target keys to keep in list format.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
note:
|
||||||
|
- Connected green wire
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
note:
|
||||||
|
- Connected blue wire
|
||||||
|
- Configured by Paul
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
comment: Needs reconfiguration
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: keep selective keys from dict/list of dict data
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.keep_keys(target=['description', 'name', 'mtu', 'duplex', 'enabled', 'vifs', 'vlan_id']) }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [keep selective keys from python dict/list of dict] ****************************************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "note": [
|
||||||
|
# "Connected green wire"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "note": [
|
||||||
|
# "Connected blue wire",
|
||||||
|
# "Configured by Paul"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "comment": "Needs reconfiguration",
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
# Read vars_file 'example.yaml'
|
||||||
|
|
||||||
|
# TASK [debug] *************************************************************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
note:
|
||||||
|
- Connected green wire
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
note:
|
||||||
|
- Connected blue wire
|
||||||
|
- Configured by Paul
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
comment: Needs reconfiguration
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: keep selective keys from dict/list of dict data
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.keep_keys(target=['desc', 'name'], matching_parameter= 'starts_with') }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [keep selective keys from python dict/list of dict] **************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "note": [
|
||||||
|
# "Connected green wire"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "note": [
|
||||||
|
# "Connected blue wire",
|
||||||
|
# "Configured by Paul"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "comment": "Needs reconfiguration",
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
# Read vars_file 'example.yaml'
|
||||||
|
|
||||||
|
# TASK [debug] **********************************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "name": "eth0"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "name": "eth1",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Sagar Paul (@KB-perByte)
|
||||||
|
|
||||||
|
|
||||||
|
.. 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.
|
|
@ -0,0 +1,390 @@
|
||||||
|
.. _ansible.utils.remove_keys_filter:
|
||||||
|
|
||||||
|
|
||||||
|
*************************
|
||||||
|
ansible.utils.remove_keys
|
||||||
|
*************************
|
||||||
|
|
||||||
|
**Remove specific keys from a data recursively.**
|
||||||
|
|
||||||
|
|
||||||
|
Version added: 2.5.0
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- This plugin removes specific keys from a provided data recursively.
|
||||||
|
- Matching parameter defaults to equals unless ``matching_parameter`` is explicitly mentioned.
|
||||||
|
- Using the parameters below- ``data|ansible.utils.remove_keys(target([....]``))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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">raw</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>This option represents a list of dictionaries or a dictionary with any level of nesting data.</div>
|
||||||
|
<div>For example <code>config_data|ansible.utils.remove_keys(target([....]</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>matching_parameter</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>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>starts_with</li>
|
||||||
|
<li>ends_with</li>
|
||||||
|
<li>regex</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Specify the matching configuration of target keys and data attributes.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>target</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Specify the target keys to remove in list format.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
note:
|
||||||
|
- Connected green wire
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
note:
|
||||||
|
- Connected blue wire
|
||||||
|
- Configured by Paul
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
comment: Needs reconfiguration
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: remove multiple keys from a provided data
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.remove_keys(target=['note', 'comment']) }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [remove multiple keys from a provided data] ***************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "note": [
|
||||||
|
# "Connected green wire"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "note": [
|
||||||
|
# "Connected blue wire",
|
||||||
|
# "Configured by Paul"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "comment": "Needs reconfiguration",
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
# Read vars_file 'example.yaml'
|
||||||
|
|
||||||
|
# TASK [debug] ********************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
note:
|
||||||
|
- Connected green wire
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
note:
|
||||||
|
- Connected blue wire
|
||||||
|
- Configured by Paul
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
comment: Needs reconfiguration
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: remove multiple keys from a provided data
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.remove_keys(target=['^note$', '^comment'], matching_parameter= 'regex') }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [remove multiple keys from a provided data] ***********************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "note": [
|
||||||
|
# "Connected green wire"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "note": [
|
||||||
|
# "Connected blue wire",
|
||||||
|
# "Configured by Paul"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "comment": "Needs reconfiguration",
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
# Read vars_file 'example.yaml'
|
||||||
|
|
||||||
|
# TASK [debug] *****************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Sagar Paul (@KB-perByte)
|
||||||
|
|
||||||
|
|
||||||
|
.. 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.
|
|
@ -0,0 +1,398 @@
|
||||||
|
.. _ansible.utils.replace_keys_filter:
|
||||||
|
|
||||||
|
|
||||||
|
**************************
|
||||||
|
ansible.utils.replace_keys
|
||||||
|
**************************
|
||||||
|
|
||||||
|
**Replaces specific keys with their after value from a data recursively.**
|
||||||
|
|
||||||
|
|
||||||
|
Version added: 2.5.0
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- This plugin replaces specific keys with their after value from a data recursively.
|
||||||
|
- Matching parameter defaults to equals unless ``matching_parameter`` is explicitly mentioned.
|
||||||
|
- Using the parameters below- ``data|ansible.utils.replace_keys(target([....]``))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Parameter</th>
|
||||||
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
|
<th>Configuration</th>
|
||||||
|
<th width="100%">Comments</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<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">raw</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>This option represents a list of dictionaries or a dictionary with any level of nesting data.</div>
|
||||||
|
<div>For example <code>config_data|ansible.utils.replace_keys(target([....]</code>)), in this case <code>config_data</code> represents this option.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>matching_parameter</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>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>starts_with</li>
|
||||||
|
<li>ends_with</li>
|
||||||
|
<li>regex</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Specify the matching configuration of target keys and data attributes.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>target</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=dictionary</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Specify the target keys to replace in list of dictionaries format containing before and after key value.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>after</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>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>after attribute key [change to]</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>before</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>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>before attribute key [to change]</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- interface_name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
- interface_name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
is_enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
is_enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
is_enabled: true
|
||||||
|
- interface_name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
is_enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: replace keys with specified keys dict/list to dict
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.replace_keys(target=[{'before':'interface_name', 'after':'name'}, {'before':'is_enabled', 'after':'enabled'}]) }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [replace keys with specified keys dict/list to dict] *************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "interface_name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "interface_name": "eth1",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "interface_name": "eth2",
|
||||||
|
# "is_enabled": false,
|
||||||
|
# "mtu": 600
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
|
||||||
|
# TASK [debug] **********************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- interface_name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
- interface_name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
is_enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
is_enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
is_enabled: true
|
||||||
|
- interface_name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
is_enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: replace keys with specified keys dict/list to dict
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.replace_keys(target=[{'before':'name', 'after':'name'}, {'before':'enabled', 'after':'enabled'}],
|
||||||
|
matching_parameter= 'ends_with') }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [replace keys with specified keys dict/list to dict] *********************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "interface_name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "interface_name": "eth1",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "interface_name": "eth2",
|
||||||
|
# "is_enabled": false,
|
||||||
|
# "mtu": 600
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
|
||||||
|
# TASK [debug] ***************************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Sagar Paul (@KB-perByte)
|
||||||
|
|
||||||
|
|
||||||
|
.. 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.
|
|
@ -0,0 +1,331 @@
|
||||||
|
#
|
||||||
|
# -*- 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 keep_keys filter plugin
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
DOCUMENTATION = """
|
||||||
|
name: keep_keys
|
||||||
|
author: Sagar Paul (@KB-perByte)
|
||||||
|
version_added: "2.5.0"
|
||||||
|
short_description: Keep specific keys from a data recursively.
|
||||||
|
description:
|
||||||
|
- This plugin keep only specified keys from a provided data recursively.
|
||||||
|
- Matching parameter defaults to equals unless C(matching_parameter) is explicitly mentioned.
|
||||||
|
- Using the parameters below- C(data|ansible.utils.keep_keys(target([....])))
|
||||||
|
options:
|
||||||
|
data:
|
||||||
|
description:
|
||||||
|
- This option represents a list of dictionaries or a dictionary with any level of nesting data.
|
||||||
|
- For example C(config_data|ansible.utils.keep_keys(target([....]))), in this case C(config_data) represents this option.
|
||||||
|
type: raw
|
||||||
|
required: True
|
||||||
|
target:
|
||||||
|
description: Specify the target keys to keep in list format.
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: True
|
||||||
|
matching_parameter:
|
||||||
|
description: Specify the matching configuration of target keys and data attributes.
|
||||||
|
type: str
|
||||||
|
choices: ["starts_with","ends_with","regex"]
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXAMPLES = r"""
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
note:
|
||||||
|
- Connected green wire
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
note:
|
||||||
|
- Connected blue wire
|
||||||
|
- Configured by Paul
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
comment: Needs reconfiguration
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: keep selective keys from dict/list of dict data
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.keep_keys(target=['description', 'name', 'mtu', 'duplex', 'enabled', 'vifs', 'vlan_id']) }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [keep selective keys from python dict/list of dict] ****************************************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "note": [
|
||||||
|
# "Connected green wire"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "note": [
|
||||||
|
# "Connected blue wire",
|
||||||
|
# "Configured by Paul"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "comment": "Needs reconfiguration",
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
# Read vars_file 'example.yaml'
|
||||||
|
|
||||||
|
# TASK [debug] *************************************************************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
note:
|
||||||
|
- Connected green wire
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
note:
|
||||||
|
- Connected blue wire
|
||||||
|
- Configured by Paul
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
comment: Needs reconfiguration
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: keep selective keys from dict/list of dict data
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.keep_keys(target=['desc', 'name'], matching_parameter= 'starts_with') }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [keep selective keys from python dict/list of dict] **************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "note": [
|
||||||
|
# "Connected green wire"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "note": [
|
||||||
|
# "Connected blue wire",
|
||||||
|
# "Configured by Paul"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "comment": "Needs reconfiguration",
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
# Read vars_file 'example.yaml'
|
||||||
|
|
||||||
|
# TASK [debug] **********************************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "name": "eth0"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "name": "eth1",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
from ansible_collections.ansible.utils.plugins.plugin_utils.keep_keys import (
|
||||||
|
keep_keys,
|
||||||
|
)
|
||||||
|
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
|
||||||
|
AnsibleArgSpecValidator,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from jinja2.filters import pass_environment
|
||||||
|
except ImportError:
|
||||||
|
from jinja2.filters import environmentfilter as pass_environment
|
||||||
|
|
||||||
|
|
||||||
|
@pass_environment
|
||||||
|
def _keep_keys(*args, **kwargs):
|
||||||
|
"""keep specific keys from a data recursively"""
|
||||||
|
|
||||||
|
keys = ["data", "target", "matching_parameter"]
|
||||||
|
data = dict(zip(keys, args[1:]))
|
||||||
|
data.update(kwargs)
|
||||||
|
aav = AnsibleArgSpecValidator(
|
||||||
|
data=data, schema=DOCUMENTATION, name="keep_keys"
|
||||||
|
)
|
||||||
|
valid, errors, updated_data = aav.validate()
|
||||||
|
if not valid:
|
||||||
|
raise AnsibleFilterError(errors)
|
||||||
|
return keep_keys(**updated_data)
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModule(object):
|
||||||
|
"""keep_keys"""
|
||||||
|
|
||||||
|
def filters(self):
|
||||||
|
|
||||||
|
"""a mapping of filter names to functions"""
|
||||||
|
return {"keep_keys": _keep_keys}
|
|
@ -0,0 +1,348 @@
|
||||||
|
#
|
||||||
|
# -*- 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 remove_keys filter plugin
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
DOCUMENTATION = """
|
||||||
|
name: remove_keys
|
||||||
|
author: Sagar Paul (@KB-perByte)
|
||||||
|
version_added: "2.5.0"
|
||||||
|
short_description: Remove specific keys from a data recursively.
|
||||||
|
description:
|
||||||
|
- This plugin removes specific keys from a provided data recursively.
|
||||||
|
- Matching parameter defaults to equals unless C(matching_parameter) is explicitly mentioned.
|
||||||
|
- Using the parameters below- C(data|ansible.utils.remove_keys(target([....])))
|
||||||
|
options:
|
||||||
|
data:
|
||||||
|
description:
|
||||||
|
- This option represents a list of dictionaries or a dictionary with any level of nesting data.
|
||||||
|
- For example C(config_data|ansible.utils.remove_keys(target([....]))), in this case C(config_data) represents this option.
|
||||||
|
type: raw
|
||||||
|
required: True
|
||||||
|
target:
|
||||||
|
description: Specify the target keys to remove in list format.
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: True
|
||||||
|
matching_parameter:
|
||||||
|
description: Specify the matching configuration of target keys and data attributes.
|
||||||
|
type: str
|
||||||
|
choices: ["starts_with","ends_with","regex"]
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXAMPLES = r"""
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
note:
|
||||||
|
- Connected green wire
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
note:
|
||||||
|
- Connected blue wire
|
||||||
|
- Configured by Paul
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
comment: Needs reconfiguration
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: remove multiple keys from a provided data
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.remove_keys(target=['note', 'comment']) }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [remove multiple keys from a provided data] ***************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "note": [
|
||||||
|
# "Connected green wire"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "note": [
|
||||||
|
# "Connected blue wire",
|
||||||
|
# "Configured by Paul"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "comment": "Needs reconfiguration",
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
# Read vars_file 'example.yaml'
|
||||||
|
|
||||||
|
# TASK [debug] ********************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
note:
|
||||||
|
- Connected green wire
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
note:
|
||||||
|
- Connected blue wire
|
||||||
|
- Configured by Paul
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
comment: Needs reconfiguration
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: remove multiple keys from a provided data
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.remove_keys(target=['^note$', '^comment'], matching_parameter= 'regex') }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [remove multiple keys from a provided data] ***********************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "note": [
|
||||||
|
# "Connected green wire"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "note": [
|
||||||
|
# "Connected blue wire",
|
||||||
|
# "Configured by Paul"
|
||||||
|
# ],
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "comment": "Needs reconfiguration",
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
# Read vars_file 'example.yaml'
|
||||||
|
|
||||||
|
# TASK [debug] *****************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
from ansible_collections.ansible.utils.plugins.plugin_utils.remove_keys import (
|
||||||
|
remove_keys,
|
||||||
|
)
|
||||||
|
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
|
||||||
|
AnsibleArgSpecValidator,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from jinja2.filters import pass_environment
|
||||||
|
except ImportError:
|
||||||
|
from jinja2.filters import environmentfilter as pass_environment
|
||||||
|
|
||||||
|
|
||||||
|
@pass_environment
|
||||||
|
def _remove_keys(*args, **kwargs):
|
||||||
|
"""remove specific keys from a data recursively"""
|
||||||
|
|
||||||
|
keys = ["data", "target", "matching_parameter"]
|
||||||
|
data = dict(zip(keys, args[1:]))
|
||||||
|
data.update(kwargs)
|
||||||
|
aav = AnsibleArgSpecValidator(
|
||||||
|
data=data, schema=DOCUMENTATION, name="remove_keys"
|
||||||
|
)
|
||||||
|
valid, errors, updated_data = aav.validate()
|
||||||
|
if not valid:
|
||||||
|
raise AnsibleFilterError(errors)
|
||||||
|
return remove_keys(**updated_data)
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModule(object):
|
||||||
|
"""remove_keys"""
|
||||||
|
|
||||||
|
def filters(self):
|
||||||
|
|
||||||
|
"""a mapping of filter names to functions"""
|
||||||
|
return {"remove_keys": _remove_keys}
|
|
@ -0,0 +1,325 @@
|
||||||
|
#
|
||||||
|
# -*- 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 replace_keys filter plugin
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
DOCUMENTATION = """
|
||||||
|
name: replace_keys
|
||||||
|
author: Sagar Paul (@KB-perByte)
|
||||||
|
version_added: "2.5.0"
|
||||||
|
short_description: Replaces specific keys with their after value from a data recursively.
|
||||||
|
description:
|
||||||
|
- This plugin replaces specific keys with their after value from a data recursively.
|
||||||
|
- Matching parameter defaults to equals unless C(matching_parameter) is explicitly mentioned.
|
||||||
|
- Using the parameters below- C(data|ansible.utils.replace_keys(target([....])))
|
||||||
|
options:
|
||||||
|
data:
|
||||||
|
description:
|
||||||
|
- This option represents a list of dictionaries or a dictionary with any level of nesting data.
|
||||||
|
- For example C(config_data|ansible.utils.replace_keys(target([....]))), in this case C(config_data) represents this option.
|
||||||
|
type: raw
|
||||||
|
required: True
|
||||||
|
target:
|
||||||
|
description: Specify the target keys to replace in list of dictionaries format containing
|
||||||
|
before and after key value.
|
||||||
|
type: list
|
||||||
|
elements: dict
|
||||||
|
required: True
|
||||||
|
suboptions:
|
||||||
|
before:
|
||||||
|
description: before attribute key [to change]
|
||||||
|
type: str
|
||||||
|
after:
|
||||||
|
description: after attribute key [change to]
|
||||||
|
type: str
|
||||||
|
matching_parameter:
|
||||||
|
description: Specify the matching configuration of target keys and data attributes.
|
||||||
|
type: str
|
||||||
|
choices: ["starts_with","ends_with","regex"]
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXAMPLES = r"""
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- interface_name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
- interface_name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
is_enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
is_enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
is_enabled: true
|
||||||
|
- interface_name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
is_enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: replace keys with specified keys dict/list to dict
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.replace_keys(target=[{'before':'interface_name', 'after':'name'}, {'before':'is_enabled', 'after':'enabled'}]) }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [replace keys with specified keys dict/list to dict] *************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "interface_name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "interface_name": "eth1",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "interface_name": "eth2",
|
||||||
|
# "is_enabled": false,
|
||||||
|
# "mtu": 600
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
|
||||||
|
# TASK [debug] **********************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
##example.yaml
|
||||||
|
interfaces:
|
||||||
|
- interface_name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
- interface_name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
is_enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
is_enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
is_enabled: true
|
||||||
|
- interface_name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
is_enabled: false
|
||||||
|
|
||||||
|
##Playbook
|
||||||
|
vars_files:
|
||||||
|
- "example.yaml"
|
||||||
|
tasks:
|
||||||
|
- name: replace keys with specified keys dict/list to dict
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data: "{{ interfaces }}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.replace_keys(target=[{'before':'name', 'after':'name'}, {'before':'enabled', 'after':'enabled'}],
|
||||||
|
matching_parameter= 'ends_with') }}"
|
||||||
|
|
||||||
|
##Output
|
||||||
|
# TASK [replace keys with specified keys dict/list to dict] *********************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "data": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "interface_name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "interface_name": "eth1",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "is_enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "interface_name": "eth2",
|
||||||
|
# "is_enabled": false,
|
||||||
|
# "mtu": 600
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# "changed": false
|
||||||
|
# }
|
||||||
|
|
||||||
|
# TASK [debug] ***************************************************************************
|
||||||
|
# ok: [localhost] => {
|
||||||
|
# "msg": [
|
||||||
|
# {
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "name": "eth0",
|
||||||
|
# "speed": "auto"
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 1",
|
||||||
|
# "duplex": "auto",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 1500,
|
||||||
|
# "name": "eth1",
|
||||||
|
# "speed": "auto",
|
||||||
|
# "vifs": [
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 100",
|
||||||
|
# "enabled": true,
|
||||||
|
# "mtu": 400,
|
||||||
|
# "vlan_id": 100
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Eth1 - VIF 101",
|
||||||
|
# "enabled": true,
|
||||||
|
# "vlan_id": 101
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# "description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
# "enabled": false,
|
||||||
|
# "mtu": 600,
|
||||||
|
# "name": "eth2"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
from ansible_collections.ansible.utils.plugins.plugin_utils.replace_keys import (
|
||||||
|
replace_keys,
|
||||||
|
)
|
||||||
|
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
|
||||||
|
AnsibleArgSpecValidator,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from jinja2.filters import pass_environment
|
||||||
|
except ImportError:
|
||||||
|
from jinja2.filters import environmentfilter as pass_environment
|
||||||
|
|
||||||
|
|
||||||
|
@pass_environment
|
||||||
|
def _replace_keys(*args, **kwargs):
|
||||||
|
"""replaces specific keys with their after value from a data recursively"""
|
||||||
|
|
||||||
|
keys = ["data", "target", "matching_parameter"]
|
||||||
|
data = dict(zip(keys, args[1:]))
|
||||||
|
data.update(kwargs)
|
||||||
|
aav = AnsibleArgSpecValidator(
|
||||||
|
data=data, schema=DOCUMENTATION, name="replace_keys"
|
||||||
|
)
|
||||||
|
valid, errors, updated_data = aav.validate()
|
||||||
|
if not valid:
|
||||||
|
raise AnsibleFilterError(errors)
|
||||||
|
return replace_keys(**updated_data)
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModule(object):
|
||||||
|
"""replace_keys"""
|
||||||
|
|
||||||
|
def filters(self):
|
||||||
|
|
||||||
|
"""a mapping of filter names to functions"""
|
||||||
|
return {"replace_keys": _replace_keys}
|
|
@ -0,0 +1,83 @@
|
||||||
|
#
|
||||||
|
# -*- 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 keep_keys plugin code
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import re
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
|
||||||
|
|
||||||
|
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 'keep_keys': {msg}".format(msg=msg)
|
||||||
|
raise AnsibleFilterError(error)
|
||||||
|
|
||||||
|
|
||||||
|
def keep_keys_from_dict_n_list(data, target, matching_parameter):
|
||||||
|
if isinstance(data, list):
|
||||||
|
list_data = [
|
||||||
|
keep_keys_from_dict_n_list(each, target, matching_parameter)
|
||||||
|
for each in data
|
||||||
|
]
|
||||||
|
return list_data
|
||||||
|
if isinstance(data, dict):
|
||||||
|
keep = {}
|
||||||
|
for k, val in data.items():
|
||||||
|
for key in target:
|
||||||
|
match = None
|
||||||
|
if not isinstance(val, (list, dict)):
|
||||||
|
if matching_parameter == "regex":
|
||||||
|
match = re.match(key, k)
|
||||||
|
if match:
|
||||||
|
keep[k] = val
|
||||||
|
elif matching_parameter == "starts_with":
|
||||||
|
if k.startswith(key):
|
||||||
|
keep[k], match = val, True
|
||||||
|
elif matching_parameter == "ends_with":
|
||||||
|
if k.endswith(key):
|
||||||
|
keep[k], match = val, True
|
||||||
|
else:
|
||||||
|
if k == key:
|
||||||
|
keep[k], match = val, True
|
||||||
|
else:
|
||||||
|
list_data = keep_keys_from_dict_n_list(
|
||||||
|
val, target, matching_parameter
|
||||||
|
)
|
||||||
|
if isinstance(list_data, list) and not match:
|
||||||
|
list_data = [r for r in list_data if r not in ([], {})]
|
||||||
|
if all(isinstance(s, str) for s in list_data):
|
||||||
|
continue
|
||||||
|
if list_data in ([], {}):
|
||||||
|
continue
|
||||||
|
keep[k] = list_data
|
||||||
|
return keep
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def keep_keys(data, target, matching_parameter="equality"):
|
||||||
|
"""keep selective keys recursively from a given data"
|
||||||
|
:param data: The data passed in (data|keep_keys(...))
|
||||||
|
:type data: raw
|
||||||
|
:param target: List of keys on with operation is to be performed
|
||||||
|
:type data: list
|
||||||
|
:type elements: string
|
||||||
|
:param matching_parameter: matching type of the target keys with data keys
|
||||||
|
:type data: str
|
||||||
|
"""
|
||||||
|
if not isinstance(data, (list, dict)):
|
||||||
|
_raise_error("Input is not valid for keep operation")
|
||||||
|
data = keep_keys_from_dict_n_list(data, target, matching_parameter)
|
||||||
|
return data
|
|
@ -0,0 +1,83 @@
|
||||||
|
#
|
||||||
|
# -*- 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 remove_keys plugin code
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import re
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
|
||||||
|
|
||||||
|
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 'remove_keys': {msg}".format(msg=msg)
|
||||||
|
raise AnsibleFilterError(error)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_keys_from_dict_n_list(data, target, matching_parameter):
|
||||||
|
if isinstance(data, dict):
|
||||||
|
for key in set(target):
|
||||||
|
for k in list(data.keys()):
|
||||||
|
if matching_parameter == "regex":
|
||||||
|
if re.match(key, k):
|
||||||
|
del data[k]
|
||||||
|
elif matching_parameter == "starts_with":
|
||||||
|
if k.startswith(key):
|
||||||
|
del data[k]
|
||||||
|
elif matching_parameter == "ends_with":
|
||||||
|
if k.endswith(key):
|
||||||
|
del data[k]
|
||||||
|
else:
|
||||||
|
if k == key:
|
||||||
|
del data[k]
|
||||||
|
for k, v in data.items():
|
||||||
|
remove_keys_from_dict_n_list(v, target, matching_parameter)
|
||||||
|
elif isinstance(data, list):
|
||||||
|
for i in data:
|
||||||
|
remove_keys_from_dict_n_list(i, target, matching_parameter)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def clear_empty_data(data):
|
||||||
|
if isinstance(data, dict):
|
||||||
|
# for k in list(data.keys()):
|
||||||
|
# if not data.get(k, {}):
|
||||||
|
# del data[k]
|
||||||
|
for k, v in data.items():
|
||||||
|
data[k] = clear_empty_data(v)
|
||||||
|
if isinstance(data, list):
|
||||||
|
temp = []
|
||||||
|
for i in data:
|
||||||
|
if i:
|
||||||
|
temp.append(clear_empty_data(i))
|
||||||
|
return temp
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def remove_keys(data, target, matching_parameter="equality"):
|
||||||
|
"""Remove unwanted keys recursively from a given data"
|
||||||
|
:param data: The data passed in (data|remove_keys(...))
|
||||||
|
:type data: raw
|
||||||
|
:param target: List of keys on with operation is to be performed
|
||||||
|
:type data: list
|
||||||
|
:type elements: string
|
||||||
|
:param matching_parameter: matching type of the target keys with data keys
|
||||||
|
:type data: str
|
||||||
|
"""
|
||||||
|
if not isinstance(data, (list, dict)):
|
||||||
|
_raise_error("Input is not valid for attribute removal")
|
||||||
|
data = remove_keys_from_dict_n_list(data, target, matching_parameter)
|
||||||
|
data = clear_empty_data(data)
|
||||||
|
return data
|
|
@ -0,0 +1,67 @@
|
||||||
|
#
|
||||||
|
# -*- 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 replace_keys plugin code
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import re
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
|
||||||
|
|
||||||
|
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 'replace_keys': {msg}".format(msg=msg)
|
||||||
|
raise AnsibleFilterError(error)
|
||||||
|
|
||||||
|
|
||||||
|
def replace_keys_from_dict_n_list(data, target, matching_parameter):
|
||||||
|
if isinstance(data, dict):
|
||||||
|
for key in target:
|
||||||
|
for k in list(data.keys()):
|
||||||
|
if matching_parameter == "regex":
|
||||||
|
if re.match(key.get("before"), k):
|
||||||
|
data[key.get("after")] = data.pop(k)
|
||||||
|
elif matching_parameter == "starts_with":
|
||||||
|
if k.startswith(key.get("before")):
|
||||||
|
data[key.get("after")] = data.pop(k)
|
||||||
|
elif matching_parameter == "ends_with":
|
||||||
|
if k.endswith(key.get("before")):
|
||||||
|
data[key.get("after")] = data.pop(k)
|
||||||
|
else:
|
||||||
|
if k == key.get("before"):
|
||||||
|
data[key.get("after")] = data.pop(k)
|
||||||
|
for k, v in data.items():
|
||||||
|
replace_keys_from_dict_n_list(v, target, matching_parameter)
|
||||||
|
elif isinstance(data, list):
|
||||||
|
for i in data:
|
||||||
|
replace_keys_from_dict_n_list(i, target, matching_parameter)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def replace_keys(data, target, matching_parameter="equality"):
|
||||||
|
"""replaces specific keys with mentioned after data"
|
||||||
|
:param data: The data passed in (data|replace_keys(...))
|
||||||
|
:type data: raw
|
||||||
|
:param target: List of keys on with operation is to be performed
|
||||||
|
:type data: list
|
||||||
|
:type elements: string
|
||||||
|
:param matching_parameter: matching type of the target keys with data keys
|
||||||
|
:type data: list
|
||||||
|
:type elements: dict
|
||||||
|
"""
|
||||||
|
if not isinstance(data, (list, dict)):
|
||||||
|
_raise_error("Input is not valid for replace operation")
|
||||||
|
data = replace_keys_from_dict_n_list(data, target, matching_parameter)
|
||||||
|
return data
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
- name: Recursively find all test files
|
||||||
|
find:
|
||||||
|
file_type: file
|
||||||
|
paths: "{{ role_path }}/tasks"
|
||||||
|
recurse: false
|
||||||
|
use_regex: true
|
||||||
|
patterns:
|
||||||
|
- '^(?!_|main).+$'
|
||||||
|
delegate_to: localhost
|
||||||
|
register: found
|
||||||
|
|
||||||
|
- include: "{{ item.path }}"
|
||||||
|
loop: "{{ found.files }}"
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
- name: Setup data as facts
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data:
|
||||||
|
- interface_name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
- interface_name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
is_enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
is_enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
is_enabled: true
|
||||||
|
- interface_name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
is_enabled: false
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.keep_keys(target=['desc', 'interface_'], matching_parameter= 'starts_with') }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert result dicts
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- keep['starts_with'] == result['msg']
|
||||||
|
|
||||||
|
- name: Setup data as facts for equivalent
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data:
|
||||||
|
- interface_name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
- interface_name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
is_enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
is_enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
is_enabled: true
|
||||||
|
- interface_name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
is_enabled: false
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.keep_keys(target=['interface_name', 'is_enabled', 'vlan_id']) }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert result dicts
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- keep_default['default'] == result['msg']
|
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
keep:
|
||||||
|
starts_with:
|
||||||
|
- interface_name: eth0
|
||||||
|
- interface_name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
vifs:
|
||||||
|
- description: Eth1 - VIF 100
|
||||||
|
- description: Eth1 - VIF 101
|
||||||
|
- interface_name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
|
||||||
|
keep_default:
|
||||||
|
default:
|
||||||
|
- interface_name: eth0
|
||||||
|
- interface_name: eth1
|
||||||
|
is_enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
is_enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
is_enabled: true
|
||||||
|
- interface_name: eth2
|
||||||
|
is_enabled: false
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
- name: Recursively find all test files
|
||||||
|
find:
|
||||||
|
file_type: file
|
||||||
|
paths: "{{ role_path }}/tasks"
|
||||||
|
recurse: false
|
||||||
|
use_regex: true
|
||||||
|
patterns:
|
||||||
|
- '^(?!_|main).+$'
|
||||||
|
delegate_to: localhost
|
||||||
|
register: found
|
||||||
|
|
||||||
|
- include: "{{ item.path }}"
|
||||||
|
loop: "{{ found.files }}"
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
- name: Setup data as facts for remove integration test
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
comment: test interface
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
notes:
|
||||||
|
- note 1
|
||||||
|
- note 2
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.remove_keys(target=['notes', 'comment']) }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert result dicts
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- remove['default'] == result['msg']
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
remove:
|
||||||
|
default:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
- name: Recursively find all test files
|
||||||
|
find:
|
||||||
|
file_type: file
|
||||||
|
paths: "{{ role_path }}/tasks"
|
||||||
|
recurse: false
|
||||||
|
use_regex: true
|
||||||
|
patterns:
|
||||||
|
- '^(?!_|main).+$'
|
||||||
|
delegate_to: localhost
|
||||||
|
register: found
|
||||||
|
|
||||||
|
- include: "{{ item.path }}"
|
||||||
|
loop: "{{ found.files }}"
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
- name: Setup data as facts for replace integration test
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
data:
|
||||||
|
- interface_name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
- interface_name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- interface_name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ data|ansible.utils.replace_keys(target=[{'before':'interface_name', 'after':'name'}]) }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert result dicts
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- replace['default'] == result['msg']
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
replace:
|
||||||
|
default:
|
||||||
|
- name: eth0
|
||||||
|
enabled: true
|
||||||
|
duplex: auto
|
||||||
|
speed: auto
|
||||||
|
- name: eth1
|
||||||
|
description: Configured by Ansible - Interface 1
|
||||||
|
mtu: 1500
|
||||||
|
speed: auto
|
||||||
|
duplex: auto
|
||||||
|
enabled: true
|
||||||
|
vifs:
|
||||||
|
- vlan_id: 100
|
||||||
|
description: Eth1 - VIF 100
|
||||||
|
mtu: 400
|
||||||
|
enabled: true
|
||||||
|
- vlan_id: 101
|
||||||
|
description: Eth1 - VIF 101
|
||||||
|
enabled: true
|
||||||
|
- name: eth2
|
||||||
|
description: Configured by Ansible - Interface 2 (ADMIN DOWN)
|
||||||
|
mtu: 600
|
||||||
|
enabled: false
|
|
@ -0,0 +1,233 @@
|
||||||
|
# -*- 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)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
from ansible_collections.ansible.utils.plugins.filter.keep_keys import (
|
||||||
|
_keep_keys,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestKeepKeys(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_keep_filter_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = ["interface_name", "is_enabled"]
|
||||||
|
output = [
|
||||||
|
{"interface_name": "eth0"},
|
||||||
|
{
|
||||||
|
"is_enabled": True,
|
||||||
|
"vifs": [{"is_enabled": True}, {"is_enabled": True}],
|
||||||
|
"interface_name": "eth1",
|
||||||
|
},
|
||||||
|
{"is_enabled": True, "interface_name": "eth2"},
|
||||||
|
]
|
||||||
|
args = ["", data, target]
|
||||||
|
|
||||||
|
result = _keep_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_keep_filter_match_starts_with_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = ["interface", "is_"]
|
||||||
|
output = [
|
||||||
|
{"interface_name": "eth0"},
|
||||||
|
{
|
||||||
|
"is_enabled": True,
|
||||||
|
"vifs": [{"is_enabled": True}, {"is_enabled": True}],
|
||||||
|
"interface_name": "eth1",
|
||||||
|
},
|
||||||
|
{"is_enabled": True, "interface_name": "eth2"},
|
||||||
|
]
|
||||||
|
args = ["", data, target, "starts_with"]
|
||||||
|
|
||||||
|
result = _keep_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_keep_filter_match_ends_with_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = ["_name", "_enabled"]
|
||||||
|
output = [
|
||||||
|
{"interface_name": "eth0"},
|
||||||
|
{
|
||||||
|
"is_enabled": True,
|
||||||
|
"vifs": [{"is_enabled": True}, {"is_enabled": True}],
|
||||||
|
"interface_name": "eth1",
|
||||||
|
},
|
||||||
|
{"is_enabled": True, "interface_name": "eth2"},
|
||||||
|
]
|
||||||
|
args = ["", data, target, "ends_with"]
|
||||||
|
|
||||||
|
result = _keep_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_keep_filter_match_regex_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = ["^interface_name$", "is_enabled"]
|
||||||
|
output = [
|
||||||
|
{"interface_name": "eth0"},
|
||||||
|
{
|
||||||
|
"is_enabled": True,
|
||||||
|
"vifs": [{"is_enabled": True}, {"is_enabled": True}],
|
||||||
|
"interface_name": "eth1",
|
||||||
|
},
|
||||||
|
{"is_enabled": True, "interface_name": "eth2"},
|
||||||
|
]
|
||||||
|
args = ["", data, target, "regex"]
|
||||||
|
|
||||||
|
result = _keep_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_invalid_data(self):
|
||||||
|
self.maxDiff = None
|
||||||
|
target = ["a", "b"]
|
||||||
|
args = ["", "string data", target]
|
||||||
|
with self.assertRaises(AnsibleFilterError) as error:
|
||||||
|
_keep_keys(*args)
|
||||||
|
self.assertIn(
|
||||||
|
"Error when using plugin 'keep_keys'", str(error.exception)
|
||||||
|
)
|
|
@ -0,0 +1,310 @@
|
||||||
|
# -*- 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)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
from ansible_collections.ansible.utils.plugins.filter.remove_keys import (
|
||||||
|
_remove_keys,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestReplaceKeys(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_remove_filter_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
"extra": "remove extra",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
"comment": ["comment A", "comment B"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = ["extra", "comment"]
|
||||||
|
output = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"is_enabled": True,
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"is_enabled": True,
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"vlan_id": 100,
|
||||||
|
"mtu": 400,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"is_enabled": True,
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"mtu": 1500,
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"is_enabled": True,
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
args = ["", data, target]
|
||||||
|
|
||||||
|
result = _remove_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_remove_filter_match_starts_with_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = ["is_"]
|
||||||
|
output = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"vlan_id": 100,
|
||||||
|
"mtu": 400,
|
||||||
|
},
|
||||||
|
{"description": "Eth1 - VIF 101", "vlan_id": 101},
|
||||||
|
],
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"mtu": 1500,
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
args = ["", data, target, "starts_with"]
|
||||||
|
|
||||||
|
result = _remove_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_replace_filter_match_ends_with_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = ["_enabled"]
|
||||||
|
output = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"vlan_id": 100,
|
||||||
|
"mtu": 400,
|
||||||
|
},
|
||||||
|
{"description": "Eth1 - VIF 101", "vlan_id": 101},
|
||||||
|
],
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"mtu": 1500,
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
args = ["", data, target, "ends_with"]
|
||||||
|
|
||||||
|
result = _remove_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_replace_filter_match_regex_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = ["^desc"]
|
||||||
|
output = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"is_enabled": True,
|
||||||
|
"vifs": [
|
||||||
|
{"is_enabled": True, "vlan_id": 100, "mtu": 400},
|
||||||
|
{"is_enabled": True, "vlan_id": 101},
|
||||||
|
],
|
||||||
|
"duplex": "auto",
|
||||||
|
"mtu": 1500,
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{"is_enabled": True, "interface_name": "eth2", "mtu": 600},
|
||||||
|
]
|
||||||
|
args = ["", data, target, "regex"]
|
||||||
|
|
||||||
|
result = _remove_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_invalid_data(self):
|
||||||
|
self.maxDiff = None
|
||||||
|
target = [{"before": "pre", "after": "post"}]
|
||||||
|
args = ["", "string data", target]
|
||||||
|
with self.assertRaises(AnsibleFilterError) as error:
|
||||||
|
_remove_keys(*args)
|
||||||
|
self.assertIn(
|
||||||
|
"Error when using plugin 'remove_keys'", str(error.exception)
|
||||||
|
)
|
|
@ -0,0 +1,349 @@
|
||||||
|
# -*- 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)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
from ansible_collections.ansible.utils.plugins.filter.replace_keys import (
|
||||||
|
_replace_keys,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestReplaceKeys(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_replace_filter_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = [
|
||||||
|
{"before": "interface_name", "after": "name"},
|
||||||
|
{"before": "is_enabled", "after": "enabled"},
|
||||||
|
]
|
||||||
|
output = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"speed": "auto",
|
||||||
|
"name": "eth0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"enabled": True,
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"vlan_id": 100,
|
||||||
|
"mtu": 400,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled": True,
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"name": "eth1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
"name": "eth2",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
args = ["", data, target]
|
||||||
|
|
||||||
|
result = _replace_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_replace_filter_match_starts_with_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = [
|
||||||
|
{"before": "interface", "after": "name"},
|
||||||
|
{"before": "is", "after": "enabled"},
|
||||||
|
]
|
||||||
|
output = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"speed": "auto",
|
||||||
|
"name": "eth0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"enabled": True,
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"vlan_id": 100,
|
||||||
|
"mtu": 400,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled": True,
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"name": "eth1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
"name": "eth2",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
args = ["", data, target, "starts_with"]
|
||||||
|
|
||||||
|
result = _replace_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_replace_filter_match_ends_with_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = [
|
||||||
|
{"before": "ame", "after": "name"},
|
||||||
|
{"before": "enabled", "after": "enabled"},
|
||||||
|
]
|
||||||
|
output = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"speed": "auto",
|
||||||
|
"name": "eth0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"enabled": True,
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"vlan_id": 100,
|
||||||
|
"mtu": 400,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled": True,
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"name": "eth1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
"name": "eth2",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
args = ["", data, target, "ends_with"]
|
||||||
|
|
||||||
|
result = _replace_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_replace_filter_match_regex_plugin(self):
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"interface_name": "eth0",
|
||||||
|
"speed": "auto",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"interface_name": "eth1",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 400,
|
||||||
|
"vlan_id": 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"is_enabled": True,
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"interface_name": "eth2",
|
||||||
|
"is_enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
target = [
|
||||||
|
{"before": "^interface_name$", "after": "name"},
|
||||||
|
{"before": "is_enabled", "after": "enabled"},
|
||||||
|
]
|
||||||
|
output = [
|
||||||
|
{
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"speed": "auto",
|
||||||
|
"name": "eth0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vifs": [
|
||||||
|
{
|
||||||
|
"enabled": True,
|
||||||
|
"description": "Eth1 - VIF 100",
|
||||||
|
"vlan_id": 100,
|
||||||
|
"mtu": 400,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled": True,
|
||||||
|
"description": "Eth1 - VIF 101",
|
||||||
|
"vlan_id": 101,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"description": "Configured by Ansible - Interface 1",
|
||||||
|
"duplex": "auto",
|
||||||
|
"enabled": True,
|
||||||
|
"mtu": 1500,
|
||||||
|
"speed": "auto",
|
||||||
|
"name": "eth1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Configured by Ansible - Interface 2 (ADMIN DOWN)",
|
||||||
|
"enabled": True,
|
||||||
|
"mtu": 600,
|
||||||
|
"name": "eth2",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
args = ["", data, target, "regex"]
|
||||||
|
|
||||||
|
result = _replace_keys(*args)
|
||||||
|
self.assertEqual(result, output)
|
||||||
|
|
||||||
|
def test_invalid_data(self):
|
||||||
|
self.maxDiff = None
|
||||||
|
target = [{"before": "pre", "after": "post"}]
|
||||||
|
args = ["", "string data", target]
|
||||||
|
with self.assertRaises(AnsibleFilterError) as error:
|
||||||
|
_replace_keys(*args)
|
||||||
|
self.assertIn(
|
||||||
|
"Error when using plugin 'replace_keys'", str(error.exception)
|
||||||
|
)
|
Loading…
Reference in New Issue