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/
|
||||
|
||||
# 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.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.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.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.
|
||||
|
|
|
@ -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